[coreboot-gerrit] Patch set updated for coreboot: resource: Add prefetchable memory resource for PCI domain

Kyösti Mälkki (kyosti.malkki@gmail.com) gerrit at coreboot.org
Wed Oct 14 09:58:37 CEST 2015


Kyösti Mälkki (kyosti.malkki at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/8892

-gerrit

commit 6dd235a6d173742f4d5639e1984c94761385ab4c
Author: Kyösti Mälkki <kyosti.malkki at gmail.com>
Date:   Thu Mar 26 23:27:54 2015 +0200

    resource: Add prefetchable memory resource for PCI domain
    
    With the change, prefetchable and non-prefetchable MMIO resources will
    no longer be interleaved for the domain, but one window will appear
    below the other in memory space.
    
    There is no need to negotiate the resource limits via intermediate
    limits structure. Recursively walk the devicetree for each type of
    resource and apply the constraints directly on the domain path.
    
    Change-ID: Ibf44deab0aed0a05759e78855e23146fc45cdc43
    Signed-off-by: Kyösti Mälkki <kyosti.malkki at gmail.com>
---
 src/device/device.c     | 169 +++++++++++++-----------------------------------
 src/device/pci_device.c |   6 ++
 2 files changed, 50 insertions(+), 125 deletions(-)

diff --git a/src/device/device.c b/src/device/device.c
index cf418eb..9e7fea4 100644
--- a/src/device/device.c
+++ b/src/device/device.c
@@ -278,10 +278,11 @@ static void pick_largest_resource(void *gp, struct device *dev,
 
 static struct device *largest_resource(struct bus *bus,
 				       struct resource **result_res,
-				       unsigned long type_mask,
-				       unsigned long type)
+				       struct resource *bridge)
 {
 	struct pick_largest_state state;
+	u32 type_mask = (IORESOURCE_TYPE_MASK | IORESOURCE_PREFETCH);
+	u32 type = bridge->flags & type_mask;
 
 	state.last = *result_res;
 	state.result_dev = NULL;
@@ -295,6 +296,20 @@ static struct device *largest_resource(struct bus *bus,
 	return state.result_dev;
 }
 
+static int resource_match(struct resource *res, struct resource *lim)
+{
+	return (res->flags & IORESOURCE_TYPE_MASK) ==
+		(lim->flags & IORESOURCE_TYPE_MASK);
+}
+
+static int resource_match_bridge(struct resource *res, struct resource *win)
+{
+	u32 type_mask = (IORESOURCE_TYPE_MASK | IORESOURCE_PREFETCH);
+	if (!(res->flags & IORESOURCE_BRIDGE))
+		return 0;
+	return (res->flags & type_mask) == (win->flags & type_mask);
+}
+
 /**
  * This function is the guts of the resource allocator.
  *
@@ -324,12 +339,8 @@ static struct device *largest_resource(struct bus *bus,
  *
  * @param bus The bus we are traversing.
  * @param bridge The bridge resource which must contain the bus' resources.
- * @param type_mask This value gets ANDed with the resource type.
- * @param type This value must match the result of the AND.
- * @return TODO
  */
-static void compute_resources(struct bus *bus, struct resource *bridge,
-			      unsigned long type_mask, unsigned long type)
+static void compute_resources(struct bus *bus, struct resource *bridge)
 {
 	struct device *dev;
 	struct resource *resource;
@@ -353,17 +364,9 @@ static void compute_resources(struct bus *bus, struct resource *bridge,
 		     child_bridge = child_bridge->next) {
 			struct bus* link;
 
-			if (!(child_bridge->flags & IORESOURCE_BRIDGE)
-			    || (child_bridge->flags & type_mask) != type)
+			if (!resource_match_bridge(child_bridge, bridge))
 				continue;
 
-			/*
-			 * Split prefetchable memory if combined. Many domains
-			 * use the same address space for prefetchable memory
-			 * and non-prefetchable memory. Bridges below them need
-			 * it separated. Add the PREFETCH flag to the type_mask
-			 * and type.
-			 */
 			link = dev->link_list;
 			while (link && link->link_num !=
 					IOINDEX_LINK(child_bridge->index))
@@ -375,10 +378,7 @@ static void compute_resources(struct bus *bus, struct resource *bridge,
 				       dev_path(dev));
 			}
 
-			compute_resources(link, child_bridge,
-					  type_mask | IORESOURCE_PREFETCH,
-					  type | (child_bridge->flags &
-						  IORESOURCE_PREFETCH));
+			compute_resources(link, child_bridge);
 		}
 	}
 
@@ -390,7 +390,7 @@ static void compute_resources(struct bus *bus, struct resource *bridge,
 	 * amount of address space taken by them. Take granularity and
 	 * alignment into account.
 	 */
-	while ((dev = largest_resource(bus, &resource, type_mask, type))) {
+	while ((dev = largest_resource(bus, &resource, bridge))) {
 
 		/* Size 0 resources can be skipped. */
 		if (!resource->size)
@@ -467,13 +467,10 @@ static void compute_resources(struct bus *bus, struct resource *bridge,
  *
  * @param bus The bus we are traversing.
  * @param bridge The bridge resource which must contain the bus' resources.
- * @param type_mask This value gets ANDed with the resource type.
- * @param type This value must match the result of the AND.
  *
  * @see compute_resources
  */
-static void allocate_resources(struct bus *bus, struct resource *bridge,
-			       unsigned long type_mask, unsigned long type)
+static void allocate_resources(struct bus *bus, struct resource *bridge)
 {
 	struct device *dev;
 	struct resource *resource;
@@ -492,7 +489,7 @@ static void allocate_resources(struct bus *bus, struct resource *bridge,
 	 * Walk through all the resources on the current bus and allocate them
 	 * address space.
 	 */
-	while ((dev = largest_resource(bus, &resource, type_mask, type))) {
+	while ((dev = largest_resource(bus, &resource, bridge))) {
 
 		/* Propagate the bridge limit to the resource register. */
 		if (resource->limit > bridge->limit)
@@ -583,17 +580,9 @@ static void allocate_resources(struct bus *bus, struct resource *bridge,
 		     child_bridge = child_bridge->next) {
 			struct bus* link;
 
-			if (!(child_bridge->flags & IORESOURCE_BRIDGE) ||
-			    (child_bridge->flags & type_mask) != type)
+			if (!resource_match_bridge(child_bridge, bridge))
 				continue;
 
-			/*
-			 * Split prefetchable memory if combined. Many domains
-			 * use the same address space for prefetchable memory
-			 * and non-prefetchable memory. Bridges below them need
-			 * it separated. Add the PREFETCH flag to the type_mask
-			 * and type.
-			 */
 			link = dev->link_list;
 			while (link && link->link_num !=
 			               IOINDEX_LINK(child_bridge->index))
@@ -603,47 +592,25 @@ static void allocate_resources(struct bus *bus, struct resource *bridge,
 				       IOINDEX_LINK(child_bridge->index),
 				       dev_path(dev));
 
-			allocate_resources(link, child_bridge,
-					   type_mask | IORESOURCE_PREFETCH,
-					   type | (child_bridge->flags &
-						   IORESOURCE_PREFETCH));
+			allocate_resources(link, child_bridge);
 		}
 	}
 }
 
-static int resource_is(struct resource *res, u32 type)
-{
-	return (res->flags & IORESOURCE_TYPE_MASK) == type;
-}
-
-struct constraints {
-	struct resource io, mem;
-};
-
-static struct resource * resource_limit(struct constraints *limits, struct resource *res)
-{
-	struct resource *lim = NULL;
-
-	/* MEM, or I/O - skip any others. */
-	if (resource_is(res, IORESOURCE_MEM))
-		lim = &limits->mem;
-	else if (resource_is(res, IORESOURCE_IO))
-		lim = &limits->io;
-
-	return lim;
-}
-
-static void constrain_resources(struct device *dev, struct constraints* limits)
+static void constrain_resources(struct device *dev, struct resource *lim)
 {
 	struct device *child;
 	struct resource *res;
-	struct resource *lim;
 	struct bus *link;
 
 	/* Constrain limits based on the fixed resources of this device. */
 	for (res = dev->resource_list; res; res = res->next) {
 		if (!(res->flags & IORESOURCE_FIXED))
 			continue;
+
+		if (!resource_match(res, lim))
+			continue;
+
 		if (!res->size) {
 			/* It makes no sense to have 0-sized, fixed resources.*/
 			printk(BIOS_ERR, "skipping %s@%lx fixed resource, "
@@ -651,10 +618,6 @@ static void constrain_resources(struct device *dev, struct constraints* limits)
 			continue;
 		}
 
-		lim = resource_limit(limits, res);
-		if (!lim)
-			continue;
-
 		/*
 		 * Is it a fixed resource outside the current known region?
 		 * If so, we don't have to consider it - it will be handled
@@ -684,63 +647,35 @@ static void constrain_resources(struct device *dev, struct constraints* limits)
 	for (link = dev->link_list; link; link = link->next) {
 		for (child = link->children; child; child = child->sibling) {
 			if (child->enabled)
-				constrain_resources(child, limits);
+				constrain_resources(child, lim);
 		}
 	}
 }
 
 static void avoid_fixed_resources(struct device *dev)
 {
-	struct constraints limits;
 	struct resource *res;
-	struct resource *lim;
+	resource_t mem_limit = 0xffffffffULL;
 
 	printk(BIOS_SPEW, "%s: %s\n", __func__, dev_path(dev));
 
-	/* Initialize constraints to maximum size. */
-	limits.io.base = 0;
-	limits.io.limit = 0xffffffffffffffffULL;
-	limits.mem.base = 0;
-	limits.mem.limit = 0xffffffffffffffffULL;
-
 	/* Constrain the limits to dev's initial resources. */
 	for (res = dev->resource_list; res; res = res->next) {
 		if ((res->flags & IORESOURCE_FIXED))
 			continue;
-		printk(BIOS_SPEW, "%s:@%s %02lx limit %08llx\n", __func__,
-		       dev_path(dev), res->index, res->limit);
-
-		lim = resource_limit(&limits, res);
-		if (!lim)
-			continue;
-
-		if (res->base > lim->base)
-			lim->base = res->base;
-		if  (res->limit < lim->limit)
-			lim->limit = res->limit;
-	}
-
-	/* Look through the tree for fixed resources and update the limits. */
-	constrain_resources(dev, &limits);
-
-	/* Update dev's resources with new limits. */
-	for (res = dev->resource_list; res; res = res->next) {
-		if ((res->flags & IORESOURCE_FIXED))
-			continue;
 
-		lim = resource_limit(&limits, res);
-		if (!lim)
-			continue;
+		/* Place MEM resources one after other. */
+		if ((res->flags & IORESOURCE_MEM) && (res->limit > mem_limit))
+			res->limit = mem_limit;
 
-		/* Is the resource outside the limits? */
-		if (lim->base > res->base)
-			res->base = lim->base;
-		if (res->limit > lim->limit)
-			res->limit = lim->limit;
+		/* Look through the tree for fixed resources and update the limits. */
+		constrain_resources(dev, res);
 
 		/* MEM resources need to start at the highest address manageable. */
-		if (res->flags & IORESOURCE_MEM)
+		if (res->flags & IORESOURCE_MEM) {
 			res->base = resource_max(res);
+			mem_limit = res->base - 1;
+		}
 
 		printk(BIOS_SPEW, "%s:@%s %02lx base %08llx limit %08llx\n",
 			__func__, dev_path(dev), res->index, res->base, res->limit);
@@ -1037,16 +972,8 @@ void dev_configure(void)
 		for (res = child->resource_list; res; res = res->next) {
 			if (res->flags & IORESOURCE_FIXED)
 				continue;
-			if (res->flags & IORESOURCE_MEM) {
-				compute_resources(child->link_list,
-						  res, IORESOURCE_TYPE_MASK, IORESOURCE_MEM);
-				continue;
-			}
-			if (res->flags & IORESOURCE_IO) {
-				compute_resources(child->link_list,
-						  res, IORESOURCE_TYPE_MASK, IORESOURCE_IO);
-				continue;
-			}
+
+			compute_resources(child->link_list, res);
 		}
 	}
 
@@ -1064,16 +991,8 @@ void dev_configure(void)
 		for (res = child->resource_list; res; res = res->next) {
 			if (res->flags & IORESOURCE_FIXED)
 				continue;
-			if (res->flags & IORESOURCE_MEM) {
-				allocate_resources(child->link_list,
-						   res, IORESOURCE_TYPE_MASK, IORESOURCE_MEM);
-				continue;
-			}
-			if (res->flags & IORESOURCE_IO) {
-				allocate_resources(child->link_list,
-						   res, IORESOURCE_TYPE_MASK, IORESOURCE_IO);
-				continue;
-			}
+
+			allocate_resources(child->link_list, res);
 		}
 	}
 	assign_resources(root->link_list);
diff --git a/src/device/pci_device.c b/src/device/pci_device.c
index f2e4d5d..6ddbf50 100644
--- a/src/device/pci_device.c
+++ b/src/device/pci_device.c
@@ -447,6 +447,12 @@ void pci_domain_read_resources(struct device *dev)
 	res->limit = 0xffffffffULL;
 	res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
 		     IORESOURCE_ASSIGNED;
+
+	/* Initialize the system-wide memory resources constraints. */
+	res = new_resource(dev, IOINDEX_SUBTRACTIVE(2, 0));
+	res->limit = 0xffffffffULL;
+	res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_SUBTRACTIVE |
+		     IORESOURCE_ASSIGNED;
 }
 
 static void pci_set_resource(struct device *dev, struct resource *resource)



More information about the coreboot-gerrit mailing list