summary refs log tree commit diff
path: root/drivers/pci
diff options
context:
space:
mode:
authorYijing Wang <wangyijing@huawei.com>2013-01-15 11:12:20 +0800
committerBjorn Helgaas <bhelgaas@google.com>2013-01-25 09:23:08 -0700
commit05b1250048158684a9fc95da5904e12cd6beefd3 (patch)
treec375492175e413b5462f2dc484ec96456d00f7f8 /drivers/pci
parentba518e3c177547dfebf7fa7252cea0c850e7ce25 (diff)
downloadlinux-05b1250048158684a9fc95da5904e12cd6beefd3.tar.gz
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.c29
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;