diff options
author | Yijing Wang <wangyijing@huawei.com> | 2013-01-15 04:12:20 +0100 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-01-25 17:23:08 +0100 |
commit | 05b1250048158684a9fc95da5904e12cd6beefd3 (patch) | |
tree | c375492175e413b5462f2dc484ec96456d00f7f8 /drivers/pci | |
parent | PCI: pciehp: Iterate over all devices in slot, not functions 0-7 (diff) | |
download | linux-05b1250048158684a9fc95da5904e12cd6beefd3.tar.xz linux-05b1250048158684a9fc95da5904e12cd6beefd3.zip |
PCI: cpcihp: Iterate over all devices in slot, not functions 0-7
Iterate through devices in a slot by using the upstream bridge's
"bus->devices" list instead of assuming they are functions 0-7. It's
possible there are several slots on the same pci_bus, so restrict it to
only devices matching this slot's device number.
ARI (which allows functions 0-255) is a PCIe-only feature, and this is
a PCI hotplug driver, so we shouldn't find anything other than functions
0-7, but it's better to iterate the same way as other hotplug drivers.
[bhelgaas: changelog, check PCI_SLOT, fix cpci_unconfigure_slot()]
Signed-off-by: Yijing Wang <wangyijing@huawei.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/cpci_hotplug_pci.c | 29 |
1 files changed, 11 insertions, 18 deletions
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index dcc75c785443..d8add34177f2 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c @@ -252,8 +252,8 @@ int cpci_led_off(struct slot* slot) int __ref cpci_configure_slot(struct slot *slot) { + struct pci_dev *dev; struct pci_bus *parent; - int fn; dbg("%s - enter", __func__); @@ -282,18 +282,13 @@ int __ref cpci_configure_slot(struct slot *slot) } parent = slot->dev->bus; - for (fn = 0; fn < 8; fn++) { - struct pci_dev *dev; - - dev = pci_get_slot(parent, - PCI_DEVFN(PCI_SLOT(slot->devfn), fn)); - if (!dev) + list_for_each_entry(dev, &parent->devices, bus_list) + if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn)) continue; if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) pci_hp_add_bridge(dev); - pci_dev_put(dev); - } + pci_assign_unassigned_bridge_resources(parent->self); @@ -305,8 +300,7 @@ int __ref cpci_configure_slot(struct slot *slot) int cpci_unconfigure_slot(struct slot* slot) { - int i; - struct pci_dev *dev; + struct pci_dev *dev, *temp; dbg("%s - enter", __func__); if (!slot->dev) { @@ -314,13 +308,12 @@ int cpci_unconfigure_slot(struct slot* slot) return -ENODEV; } - for (i = 0; i < 8; i++) { - dev = pci_get_slot(slot->bus, - PCI_DEVFN(PCI_SLOT(slot->devfn), i)); - if (dev) { - pci_stop_and_remove_bus_device(dev); - pci_dev_put(dev); - } + list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) { + if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn)) + continue; + pci_dev_get(dev); + pci_stop_and_remove_bus_device(dev); + pci_dev_put(dev); } pci_dev_put(slot->dev); slot->dev = NULL; |