Skip to content

Commit

Permalink
PCI: sgihp: Iterate over all devices in slot, not functions 0-7
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Yijing Wang authored and Bjorn Helgaas committed Jan 25, 2013
1 parent 05b1250 commit ab6380e
Showing 1 changed file with 29 additions and 34 deletions.
63 changes: 29 additions & 34 deletions drivers/pci/hotplug/sgi_hotplug.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
struct slot *slot = bss_hotplug_slot->private;
struct pci_bus *new_bus = NULL;
struct pci_dev *dev;
int func, num_funcs;
int num_funcs;
int new_ppb = 0;
int rc;
char *ssdt = NULL;
Expand Down Expand Up @@ -381,29 +381,26 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
* to the Linux PCI interface and tell the drivers
* about them.
*/
for (func = 0; func < num_funcs; func++) {
dev = pci_get_slot(slot->pci_bus,
PCI_DEVFN(slot->device_num + 1,
PCI_FUNC(func)));
if (dev) {
/* Need to do slot fixup on PPB before fixup of children
* (PPB's pcidev_info needs to be in pcidev_info list
* before child's SN_PCIDEV_INFO() call to setup
* pdi_host_pcidev_info).
*/
pcibios_fixup_device_resources(dev);
if (SN_ACPI_BASE_SUPPORT())
sn_acpi_slot_fixup(dev);
else
sn_io_slot_fixup(dev);
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
pci_hp_add_bridge(dev);
if (dev->subordinate) {
new_bus = dev->subordinate;
new_ppb = 1;
}
list_for_each_entry(dev, &slot->pci_bus->devices, bus_list) {
if (PCI_SLOT(dev->devfn) != slot->device_num + 1)
continue;

/* Need to do slot fixup on PPB before fixup of children
* (PPB's pcidev_info needs to be in pcidev_info list
* before child's SN_PCIDEV_INFO() call to setup
* pdi_host_pcidev_info).
*/
pcibios_fixup_device_resources(dev);
if (SN_ACPI_BASE_SUPPORT())
sn_acpi_slot_fixup(dev);
else
sn_io_slot_fixup(dev);
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
pci_hp_add_bridge(dev);
if (dev->subordinate) {
new_bus = dev->subordinate;
new_ppb = 1;
}
pci_dev_put(dev);
}
}

Expand Down Expand Up @@ -485,8 +482,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
{
struct slot *slot = bss_hotplug_slot->private;
struct pci_dev *dev;
int func;
struct pci_dev *dev, *temp;
int rc;
acpi_owner_id ssdt_id = 0;

Expand Down Expand Up @@ -546,15 +542,14 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
}

/* Free the SN resources assigned to the Linux device.*/
for (func = 0; func < 8; func++) {
dev = pci_get_slot(slot->pci_bus,
PCI_DEVFN(slot->device_num + 1,
PCI_FUNC(func)));
if (dev) {
sn_bus_free_data(dev);
pci_stop_and_remove_bus_device(dev);
pci_dev_put(dev);
}
list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) {
if (PCI_SLOT(dev->devfn) != slot->device_num + 1)
continue;

pci_dev_get(dev);
sn_bus_free_data(dev);
pci_stop_and_remove_bus_device(dev);
pci_dev_put(dev);
}

/* Remove the SSDT for the slot from the ACPI namespace */
Expand Down

0 comments on commit ab6380e

Please sign in to comment.