"Early" and "header" quirks use incorrect bus resources because they see the default resources assigned by pci_create_bus(), before the architecture fixes them up (typically in pcibios_fixup_bus()). Regions reserved by these quirks end up with the wrong parents. Here's the standard path for scanning a PCI root bus: pci_scan_bus or pci_scan_bus_parented pci_create_bus <-- A create with default resources pci_scan_child_bus pci_scan_slot pci_scan_single_device pci_scan_device pci_setup_device pci_fixup_device(early) <-- B pci_device_add pci_fixup_device(header) <-- C pcibios_fixup_bus <-- D fill in correct resources Early and header quirks at B and C use the default (incorrect) root bus resources rather than those filled in at D. This patch adds a new pci_scan_root_bus() function that sets the bus resources correctly from a supplied list of resources. It also marks pci_scan_bus() and pci_scan_bus_parented() as deprecated. Callers of pci_scan_bus() should switch to pci_scan_root_bus(). Callers of pci_scan_bus_parented() should use pci_create_root_bus() followed by pci_scan_child_bus(). In both cases, root bus resource fixups, e.g., in pcibios_fixup_bus(), should be removed. Signed-off-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx> --- drivers/pci/probe.c | 39 +++++++++++++++++++++++++++++++++++++-- include/linux/pci.h | 19 ++++++++----------- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 20d2d40..9cb7158 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1624,18 +1624,53 @@ struct pci_bus *pci_create_bus(struct device *parent, return pci_create_root_bus(parent, bus, ops, sysdata, NULL); } +/* + * Deprecated; use pci_create_root_bus() with non-NULL resources and + * pci_scan_child_bus() instead + */ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata) { struct pci_bus *b; b = pci_create_root_bus(parent, bus, ops, sysdata, NULL); - if (b) - b->subordinate = pci_scan_child_bus(b); + if (!b) + return NULL; + + b->subordinate = pci_scan_child_bus(b); return b; } EXPORT_SYMBOL(pci_scan_bus_parented); +/* Deprecated; use pci_scan_root_bus() with non-NULL resources instead */ +struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops, + void *sysdata) +{ + struct pci_bus *b; + + b = pci_create_root_bus(NULL, bus, ops, sysdata, NULL); + if (!b) + return NULL; + + b->subordinate = pci_scan_child_bus(b); + pci_bus_add_devices(b); + return b; +} + +struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus_num, + struct pci_ops *ops, void *sysdata, struct list_head *resources) +{ + struct pci_bus *bus; + + bus = pci_create_root_bus(parent, bus_num, ops, sysdata, resources); + if (!bus) + return NULL; + + bus->subordinate = pci_scan_child_bus(bus); + pci_bus_add_devices(bus); + return bus; +} + #ifdef CONFIG_HOTPLUG /** * pci_rescan_bus - scan a PCI bus for devices. diff --git a/include/linux/pci.h b/include/linux/pci.h index 6bdf854..03c6089 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -655,20 +655,17 @@ void pci_fixup_cardbus(struct pci_bus *); void pcibios_scan_specific_bus(int busn); extern struct pci_bus *pci_find_bus(int domain, int busnr); void pci_bus_add_devices(const struct pci_bus *bus); -struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus, - struct pci_ops *ops, void *sysdata); -static inline struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops, - void *sysdata) -{ - struct pci_bus *root_bus; - root_bus = pci_scan_bus_parented(NULL, bus, ops, sysdata); - if (root_bus) - pci_bus_add_devices(root_bus); - return root_bus; -} +struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus, + struct pci_ops *ops, void *sysdata, + struct list_head *resources); struct pci_bus *pci_create_root_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata, struct list_head *resources); +struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus, + struct pci_ops *ops, void *sysdata) + __deprecated; +struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops, + void *sysdata) __deprecated; struct pci_bus *pci_create_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata) __deprecated; struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, -- 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