so later we can do sth with those failed one Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx> --- drivers/pci/setup-bus.c | 70 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 7 deletions(-) Index: linux-2.6/drivers/pci/setup-bus.c =================================================================== --- linux-2.6.orig/drivers/pci/setup-bus.c +++ linux-2.6/drivers/pci/setup-bus.c @@ -27,7 +27,49 @@ #include <linux/slab.h> #include "pci.h" -static void pbus_assign_resources_sorted(const struct pci_bus *bus) + +static void add_to_failed_list(struct resource_list *head, struct pci_dev *dev, + struct resource *res) +{ + struct resource_list *list = head; + struct resource_list *ln = list->next; + struct resource_list *tmp; + + tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) { + pr_warning("add_to_failed_list: kmalloc() failed!\n"); + return; + } + + tmp->next = ln; + tmp->res = res; + tmp->dev = dev; + list->next = tmp; +} + +static void free_failed_list(struct resource_list *head) +{ + struct resource_list *list, *tmp; + struct resource *res; + /* + * Try to release leaf bridge's resources that there is no child + * under it + */ + for (list = head->next; list;) { + res = list->res; + res->start = 0; + res->end = 0; + res->flags = 0; + tmp = list; + list = list->next; + kfree(tmp); + } + + head->next = NULL; +} + +static void pbus_assign_resources_sorted(const struct pci_bus *bus, + struct resource_list *fail_head) { struct pci_dev *dev; struct resource *res; @@ -58,9 +100,17 @@ static void pbus_assign_resources_sorted res = list->res; idx = res - &list->dev->resource[0]; if (pci_assign_resource(list->dev, idx)) { - res->start = 0; - res->end = 0; - res->flags = 0; + if (fail_head && !pci_is_root_bus(list->dev->bus)) { + /* + * device need to keep flags and size + * for next try + */ + add_to_failed_list(fail_head, list->dev, res); + } else { + res->start = 0; + res->end = 0; + res->flags = 0; + } } tmp = list; list = list->next; @@ -577,19 +627,20 @@ void __ref pci_bus_size_bridges(struct p } EXPORT_SYMBOL(pci_bus_size_bridges); -void __ref pci_bus_assign_resources(const struct pci_bus *bus) +static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, + struct resource_list *fail_head) { struct pci_bus *b; struct pci_dev *dev; - pbus_assign_resources_sorted(bus); + pbus_assign_resources_sorted(bus, fail_head); list_for_each_entry(dev, &bus->devices, bus_list) { b = dev->subordinate; if (!b) continue; - pci_bus_assign_resources(b); + __pci_bus_assign_resources(b, fail_head); switch (dev->class >> 8) { case PCI_CLASS_BRIDGE_PCI: @@ -607,6 +658,11 @@ void __ref pci_bus_assign_resources(cons } } } + +void __ref pci_bus_assign_resources(const struct pci_bus *bus) +{ + __pci_bus_assign_resources(bus, NULL); +} EXPORT_SYMBOL(pci_bus_assign_resources); static void release_children_resource(struct resource *r) -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html