aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorYijing Wang <wangyijing@huawei.com>2013-01-14 22:12:21 -0500
committerBjorn Helgaas <bhelgaas@google.com>2013-01-25 11:23:08 -0500
commitab6380ef01983e977c147cb8bb040f57e4fe2d55 (patch)
tree29c05b6eae690ffe7f8a100e064030d0dc7743bc /drivers/pci
parent05b1250048158684a9fc95da5904e12cd6beefd3 (diff)
PCI: sgihp: 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 disable_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/sgi_hotplug.c63
1 files changed, 29 insertions, 34 deletions
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index f64ca92253da..14ad22e07e00 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -334,7 +334,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
334 struct slot *slot = bss_hotplug_slot->private; 334 struct slot *slot = bss_hotplug_slot->private;
335 struct pci_bus *new_bus = NULL; 335 struct pci_bus *new_bus = NULL;
336 struct pci_dev *dev; 336 struct pci_dev *dev;
337 int func, num_funcs; 337 int num_funcs;
338 int new_ppb = 0; 338 int new_ppb = 0;
339 int rc; 339 int rc;
340 char *ssdt = NULL; 340 char *ssdt = NULL;
@@ -381,29 +381,26 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
381 * to the Linux PCI interface and tell the drivers 381 * to the Linux PCI interface and tell the drivers
382 * about them. 382 * about them.
383 */ 383 */
384 for (func = 0; func < num_funcs; func++) { 384 list_for_each_entry(dev, &slot->pci_bus->devices, bus_list) {
385 dev = pci_get_slot(slot->pci_bus, 385 if (PCI_SLOT(dev->devfn) != slot->device_num + 1)
386 PCI_DEVFN(slot->device_num + 1, 386 continue;
387 PCI_FUNC(func))); 387
388 if (dev) { 388 /* Need to do slot fixup on PPB before fixup of children
389 /* Need to do slot fixup on PPB before fixup of children 389 * (PPB's pcidev_info needs to be in pcidev_info list
390 * (PPB's pcidev_info needs to be in pcidev_info list 390 * before child's SN_PCIDEV_INFO() call to setup
391 * before child's SN_PCIDEV_INFO() call to setup 391 * pdi_host_pcidev_info).
392 * pdi_host_pcidev_info). 392 */
393 */ 393 pcibios_fixup_device_resources(dev);
394 pcibios_fixup_device_resources(dev); 394 if (SN_ACPI_BASE_SUPPORT())
395 if (SN_ACPI_BASE_SUPPORT()) 395 sn_acpi_slot_fixup(dev);
396 sn_acpi_slot_fixup(dev); 396 else
397 else 397 sn_io_slot_fixup(dev);
398 sn_io_slot_fixup(dev); 398 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
399 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 399 pci_hp_add_bridge(dev);
400 pci_hp_add_bridge(dev); 400 if (dev->subordinate) {
401 if (dev->subordinate) { 401 new_bus = dev->subordinate;
402 new_bus = dev->subordinate; 402 new_ppb = 1;
403 new_ppb = 1;
404 }
405 } 403 }
406 pci_dev_put(dev);
407 } 404 }
408 } 405 }
409 406
@@ -485,8 +482,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
485static int disable_slot(struct hotplug_slot *bss_hotplug_slot) 482static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
486{ 483{
487 struct slot *slot = bss_hotplug_slot->private; 484 struct slot *slot = bss_hotplug_slot->private;
488 struct pci_dev *dev; 485 struct pci_dev *dev, *temp;
489 int func;
490 int rc; 486 int rc;
491 acpi_owner_id ssdt_id = 0; 487 acpi_owner_id ssdt_id = 0;
492 488
@@ -546,15 +542,14 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
546 } 542 }
547 543
548 /* Free the SN resources assigned to the Linux device.*/ 544 /* Free the SN resources assigned to the Linux device.*/
549 for (func = 0; func < 8; func++) { 545 list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) {
550 dev = pci_get_slot(slot->pci_bus, 546 if (PCI_SLOT(dev->devfn) != slot->device_num + 1)
551 PCI_DEVFN(slot->device_num + 1, 547 continue;
552 PCI_FUNC(func))); 548
553 if (dev) { 549 pci_dev_get(dev);
554 sn_bus_free_data(dev); 550 sn_bus_free_data(dev);
555 pci_stop_and_remove_bus_device(dev); 551 pci_stop_and_remove_bus_device(dev);
556 pci_dev_put(dev); 552 pci_dev_put(dev);
557 }
558 } 553 }
559 554
560 /* Remove the SSDT for the slot from the ACPI namespace */ 555 /* Remove the SSDT for the slot from the ACPI namespace */