[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
Thu Nov 17 08:09:45 CET 2016


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

-gerrit

commit 5da47dcd56fc7b657c9dc89f98a6a53ec930b1c8
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 9ea32cc..28b0bcb 100644
--- a/src/device/device.c
+++ b/src/device/device.c
@@ -285,10 +285,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;
@@ -302,6 +303,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.
  *
@@ -331,12 +346,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;
@@ -360,17 +371,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))
@@ -382,10 +385,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);
 		}
 	}
 
@@ -397,7 +397,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)
@@ -474,13 +474,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;
@@ -499,7 +496,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)
@@ -590,17 +587,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))
@@ -610,47 +599,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, "
@@ -658,10 +625,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
@@ -691,63 +654,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);
@@ -1050,16 +985,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);
 		}
 	}
 
@@ -1077,16 +1004,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 05d4051..1c448b1 100644
--- a/src/device/pci_device.c
+++ b/src/device/pci_device.c
@@ -460,6 +460,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