diff options
author | Yinghai Lu <yinghai@kernel.org> | 2012-09-17 22:14:43 -0700 |
---|---|---|
committer | Yinghai Lu <yinghai@kernel.org> | 2012-09-17 22:14:43 -0700 |
commit | e53ba5988b55adb19610c285959aec5b5a4b7d01 (patch) | |
tree | 3285fa3a6109df3c060f20b76ffe3ff40150174f | |
parent | 5c76ca3c0a80e3bdd749d605eda1c7d3febcf324 (diff) | |
download | linux-yinghai-e53ba5988b55adb19610c285959aec5b5a4b7d01.tar.gz |
PCI: pci_bus_size_bridges() should not size own bridge
During checking acpiphp code, found following sequence:
pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
pci_enable_bridges(bus);
The problem is that when bus is not root bus, pci_bus_size_bridges would also size
own pci bridge bus->self if that bridge resource is not inserted before.
but later pci_bus_assign_resources will not allocate those size bridge res.
So try make it less confusing, let it does not include self sizing.
and add with_self parameter info __pci_bus_size_bridge()
Fixes caller in pci hotplug componets.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 3 | ||||
-rw-r--r-- | drivers/pci/setup-bus.c | 24 | ||||
-rw-r--r-- | include/linux/pci.h | 1 |
3 files changed, 18 insertions, 10 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 085eec7a3706ae..6cb1923bf7f95f 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -842,7 +842,8 @@ static int __ref enable_device(struct acpiphp_slot *slot) max = pci_scan_bridge(bus, dev, max, pass); if (pass && dev->subordinate) { check_hotplug_bridge(slot, dev); - pci_bus_size_bridges(dev->subordinate); + pci_bus_size_bridges_with_self( + dev->subordinate); } } } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 31821d463fac15..85f7ec7340fa86 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1044,8 +1044,8 @@ handle_done: ; } -void __ref __pci_bus_size_bridges(struct pci_bus *bus, - struct list_head *realloc_head) +static void __ref __pci_bus_size_bridges(struct pci_bus *bus, + struct list_head *realloc_head, bool with_self) { struct pci_dev *dev; unsigned long mask, prefmask; @@ -1063,13 +1063,13 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus, case PCI_CLASS_BRIDGE_PCI: default: - __pci_bus_size_bridges(b, realloc_head); + __pci_bus_size_bridges(b, realloc_head, true); break; } } - /* The root bus? */ - if (!bus->self) + /* Is root bus or not wanted? */ + if (!bus->self || !with_self) return; switch (bus->self->class >> 8) { @@ -1109,9 +1109,15 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus, } } +void __ref pci_bus_size_bridges_with_self(struct pci_bus *bus) +{ + __pci_bus_size_bridges(bus, NULL, true); +} +EXPORT_SYMBOL(pci_bus_size_bridges_with_self); + void __ref pci_bus_size_bridges(struct pci_bus *bus) { - __pci_bus_size_bridges(bus, NULL); + __pci_bus_size_bridges(bus, NULL, false); } EXPORT_SYMBOL(pci_bus_size_bridges); @@ -1424,7 +1430,7 @@ again: /* Depth first, calculate sizes and alignments of all subordinate buses. */ list_for_each_entry(bus, &pci_root_buses, node) - __pci_bus_size_bridges(bus, add_list); + __pci_bus_size_bridges(bus, add_list, false); /* Depth last, allocate resources and update the hardware. */ list_for_each_entry(bus, &pci_root_buses, node) @@ -1501,7 +1507,7 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) IORESOURCE_PREFETCH; again: - __pci_bus_size_bridges(parent, &add_list); + __pci_bus_size_bridges(parent, &add_list, true); __pci_bridge_assign_resources(bridge, &add_list, &fail_head); BUG_ON(!list_empty(&add_list)); tried_times++; @@ -1562,7 +1568,7 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus) dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) if (dev->subordinate) __pci_bus_size_bridges(dev->subordinate, - &add_list); + &add_list, true); up_read(&pci_bus_sem); __pci_bus_assign_resources(bus, &add_list, NULL); BUG_ON(!list_empty(&add_list)); diff --git a/include/linux/pci.h b/include/linux/pci.h index 02b8e10052f980..740407726e079c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -978,6 +978,7 @@ int pci_vpd_truncate(struct pci_dev *dev, size_t size); resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx); void pci_bus_assign_resources(const struct pci_bus *bus); void pci_bus_size_bridges(struct pci_bus *bus); +void pci_bus_size_bridges_with_self(struct pci_bus *bus); int pci_claim_resource(struct pci_dev *, int); void pci_assign_unassigned_resources(void); void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge); |