Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Yijing Wang and committed by
Bjorn Helgaas
05b12500 ba518e3c

+11 -18
+11 -18
drivers/pci/hotplug/cpci_hotplug_pci.c
··· 252 252 253 253 int __ref cpci_configure_slot(struct slot *slot) 254 254 { 255 + struct pci_dev *dev; 255 256 struct pci_bus *parent; 256 - int fn; 257 257 258 258 dbg("%s - enter", __func__); 259 259 ··· 282 282 } 283 283 parent = slot->dev->bus; 284 284 285 - for (fn = 0; fn < 8; fn++) { 286 - struct pci_dev *dev; 287 - 288 - dev = pci_get_slot(parent, 289 - PCI_DEVFN(PCI_SLOT(slot->devfn), fn)); 290 - if (!dev) 285 + list_for_each_entry(dev, &parent->devices, bus_list) 286 + if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn)) 291 287 continue; 292 288 if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || 293 289 (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) 294 290 pci_hp_add_bridge(dev); 295 - pci_dev_put(dev); 296 - } 291 + 297 292 298 293 pci_assign_unassigned_bridge_resources(parent->self); 299 294 ··· 300 305 301 306 int cpci_unconfigure_slot(struct slot* slot) 302 307 { 303 - int i; 304 - struct pci_dev *dev; 308 + struct pci_dev *dev, *temp; 305 309 306 310 dbg("%s - enter", __func__); 307 311 if (!slot->dev) { ··· 308 314 return -ENODEV; 309 315 } 310 316 311 - for (i = 0; i < 8; i++) { 312 - dev = pci_get_slot(slot->bus, 313 - PCI_DEVFN(PCI_SLOT(slot->devfn), i)); 314 - if (dev) { 315 - pci_stop_and_remove_bus_device(dev); 316 - pci_dev_put(dev); 317 - } 317 + list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) { 318 + if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn)) 319 + continue; 320 + pci_dev_get(dev); 321 + pci_stop_and_remove_bus_device(dev); 322 + pci_dev_put(dev); 318 323 } 319 324 pci_dev_put(slot->dev); 320 325 slot->dev = NULL;