Nico Huber has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/41959 )
Change subject: [WIP] device/resource_allocator_v4.5: Directly recurse in pass 2 for each bridge resource ......................................................................
[WIP] device/resource_allocator_v4.5: Directly recurse in pass 2 for each bridge resource
Change-Id: I9b31c7242f0cdf747db48203243f0e9ba6643bf4 Signed-off-by: Nico Huber nico.h@gmx.de --- M src/device/resource_allocator_v4.5.c 1 file changed, 40 insertions(+), 61 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/59/41959/1
diff --git a/src/device/resource_allocator_v4.5.c b/src/device/resource_allocator_v4.5.c index 34e9fdd..96a6503 100644 --- a/src/device/resource_allocator_v4.5.c +++ b/src/device/resource_allocator_v4.5.c @@ -394,6 +394,43 @@ }
/* + * Pass 2 of the resource allocator at the bridge level loops through + * all the resources for the bridge and assigns all the base addresses + * of its children's resources of the same type. update_bridge_resource() + * of pass 1 pre-calculated the offsets of these bases inside the bridge + * resource. Now that the bridge resource is allocated, all we have to + * do is to add its final base to these offsets. + * + * Once allocation at the current bridge is complete, resource allocator + * continues walking down the downstream bridges until it hits the leaf + * devices. + */ +static void allocate_bridge_resources(const struct device *bridge, struct resource *bridge_res) +{ + void assign_resource_cb(void *param, struct device *dev, struct resource *res) + { + /* We have to filter the same resources as update_bridge_resource(). */ + if (!res->size || !res->limit) + return; + + assign_resource(res, *(const resource_t *)param + res->base, dev); + + if (res->flags & IORESOURCE_BRIDGE) + allocate_bridge_resources(dev, res); + } + + const unsigned long type_mask = IORESOURCE_TYPE_MASK | IORESOURCE_PREFETCH; + const unsigned long type = bridge_res->flags & type_mask; + struct bus *const bus = bridge->link_list; + + if (!bus) + return; + + /* Run assign_resource_cb() for all downstream resources of the same type. */ + search_bus_resources(bus, type_mask, type, assign_resource_cb, &bridge_res->base); +} + +/* * This is where the actual allocation of resources happens during * pass 2. We construct a list of memory ranges corresponding to the * resource of a given type, then look for the biggest unallocated @@ -433,63 +470,15 @@ }
assign_resource(res, base, dev); + + if (res->flags & IORESOURCE_BRIDGE) + allocate_bridge_resources(dev, res); }
cleanup_resource_ranges(domain, &ranges, domain_res); }
/* - * Pass 2 of the resource allocator at the bridge level loops through - * all the resources for the bridge and assigns all the base addresses - * of its children's resources of the same type. update_bridge_resource() - * of pass 1 pre-calculated the offsets of these bases inside the bridge - * resource. Now that the bridge resource is allocated, all we have to - * do is to add its final base to these offsets. - * - * Once allocation at the current bridge is complete, resource allocator - * continues walking down the downstream bridges until it hits the leaf - * devices. - */ -static void allocate_bridge_resources(const struct device *bridge) -{ - void assign_resource_cb(void *param, struct device *dev, struct resource *res) - { - /* We have to filter the same resources as update_bridge_resource(). */ - if (!res->size || !res->limit) - return; - - assign_resource(res, *(const resource_t *)param + res->base, dev); - } - - const unsigned long type_mask = IORESOURCE_TYPE_MASK | IORESOURCE_PREFETCH; - struct bus *const bus = bridge->link_list; - struct resource *res; - struct device *child; - - for (res = bridge->resource_list; res != NULL; res = res->next) { - if (!res->size) - continue; - - if (!(res->flags & IORESOURCE_BRIDGE)) - continue; - - if (!(res->flags & IORESOURCE_ASSIGNED)) - continue; - - /* Run assign_resource_cb() for all downstream resources of the same type. */ - search_bus_resources(bus, type_mask, res->flags & type_mask, - assign_resource_cb, &res->base); - } - - for (child = bus->children; child != NULL; child = child->sibling) { - if (!dev_has_children(child)) - continue; - - allocate_bridge_resources(child); - } -} - -/* * Pass 2 of resource allocator begins at the domain level. Every domain * has two types of resources - io and mem. For each of these resources, * this function creates a list of memory ranges that can be used for @@ -504,8 +493,6 @@ */ static void allocate_domain_resources(const struct device *domain) { - struct device *child; - /* Resource type I/O */ allocate_toplevel_resources(domain, IORESOURCE_IO);
@@ -516,14 +503,6 @@ * on the biggest resource requirement. */ allocate_toplevel_resources(domain, IORESOURCE_MEM); - - for (child = domain->link_list->children; child; child = child->sibling) { - if (!dev_has_children(child)) - continue; - - /* Continue allocation for all downstream bridges. */ - allocate_bridge_resources(child); - } }
/*