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>
This commit is contained in:
parent
ba518e3c17
commit
05b1250048
@ -252,8 +252,8 @@ int cpci_led_off(struct slot* slot)
|
|||||||
|
|
||||||
int __ref cpci_configure_slot(struct slot *slot)
|
int __ref cpci_configure_slot(struct slot *slot)
|
||||||
{
|
{
|
||||||
|
struct pci_dev *dev;
|
||||||
struct pci_bus *parent;
|
struct pci_bus *parent;
|
||||||
int fn;
|
|
||||||
|
|
||||||
dbg("%s - enter", __func__);
|
dbg("%s - enter", __func__);
|
||||||
|
|
||||||
@ -282,18 +282,13 @@ int __ref cpci_configure_slot(struct slot *slot)
|
|||||||
}
|
}
|
||||||
parent = slot->dev->bus;
|
parent = slot->dev->bus;
|
||||||
|
|
||||||
for (fn = 0; fn < 8; fn++) {
|
list_for_each_entry(dev, &parent->devices, bus_list)
|
||||||
struct pci_dev *dev;
|
if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
|
||||||
|
|
||||||
dev = pci_get_slot(parent,
|
|
||||||
PCI_DEVFN(PCI_SLOT(slot->devfn), fn));
|
|
||||||
if (!dev)
|
|
||||||
continue;
|
continue;
|
||||||
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
|
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
|
||||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
|
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
|
||||||
pci_hp_add_bridge(dev);
|
pci_hp_add_bridge(dev);
|
||||||
pci_dev_put(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
pci_assign_unassigned_bridge_resources(parent->self);
|
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 cpci_unconfigure_slot(struct slot* slot)
|
||||||
{
|
{
|
||||||
int i;
|
struct pci_dev *dev, *temp;
|
||||||
struct pci_dev *dev;
|
|
||||||
|
|
||||||
dbg("%s - enter", __func__);
|
dbg("%s - enter", __func__);
|
||||||
if (!slot->dev) {
|
if (!slot->dev) {
|
||||||
@ -314,14 +308,13 @@ int cpci_unconfigure_slot(struct slot* slot)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) {
|
||||||
dev = pci_get_slot(slot->bus,
|
if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
|
||||||
PCI_DEVFN(PCI_SLOT(slot->devfn), i));
|
continue;
|
||||||
if (dev) {
|
pci_dev_get(dev);
|
||||||
pci_stop_and_remove_bus_device(dev);
|
pci_stop_and_remove_bus_device(dev);
|
||||||
pci_dev_put(dev);
|
pci_dev_put(dev);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
pci_dev_put(slot->dev);
|
pci_dev_put(slot->dev);
|
||||||
slot->dev = NULL;
|
slot->dev = NULL;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user