diff options
author | Yijing Wang <wangyijing@huawei.com> | 2013-01-14 22:12:21 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-01-25 11:23:08 -0500 |
commit | ab6380ef01983e977c147cb8bb040f57e4fe2d55 (patch) | |
tree | 29c05b6eae690ffe7f8a100e064030d0dc7743bc /drivers/pci | |
parent | 05b1250048158684a9fc95da5904e12cd6beefd3 (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.c | 63 |
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) | |||
485 | static int disable_slot(struct hotplug_slot *bss_hotplug_slot) | 482 | static 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 */ |