PCI: hotplug: Use global PCI rescan-remove locking
Multiple race conditions are possible between PCI hotplug and the generic PCI bus rescan and device removal that can be triggered via sysfs. To avoid those race conditions make PCI hotplug use global PCI rescan-remove locking. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
This commit is contained in:

committed by
Bjorn Helgaas

parent
5ef68e8867
commit
c4ec84c7db
@@ -40,7 +40,9 @@ int __ref shpchp_configure_device(struct slot *p_slot)
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
struct pci_dev *bridge = ctrl->pci_dev;
|
||||
struct pci_bus *parent = bridge->subordinate;
|
||||
int num;
|
||||
int num, ret = 0;
|
||||
|
||||
pci_lock_rescan_remove();
|
||||
|
||||
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
|
||||
if (dev) {
|
||||
@@ -48,13 +50,15 @@ int __ref shpchp_configure_device(struct slot *p_slot)
|
||||
"at %04x:%02x:%02x, cannot hot-add\n", pci_name(dev),
|
||||
pci_domain_nr(parent), p_slot->bus, p_slot->device);
|
||||
pci_dev_put(dev);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
|
||||
if (num == 0) {
|
||||
ctrl_err(ctrl, "No new device found\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
list_for_each_entry(dev, &parent->devices, bus_list) {
|
||||
@@ -75,7 +79,9 @@ int __ref shpchp_configure_device(struct slot *p_slot)
|
||||
|
||||
pci_bus_add_devices(parent);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
pci_unlock_rescan_remove();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int shpchp_unconfigure_device(struct slot *p_slot)
|
||||
@@ -89,6 +95,8 @@ int shpchp_unconfigure_device(struct slot *p_slot)
|
||||
ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n",
|
||||
__func__, pci_domain_nr(parent), p_slot->bus, p_slot->device);
|
||||
|
||||
pci_lock_rescan_remove();
|
||||
|
||||
list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) {
|
||||
if (PCI_SLOT(dev->devfn) != p_slot->device)
|
||||
continue;
|
||||
@@ -108,6 +116,8 @@ int shpchp_unconfigure_device(struct slot *p_slot)
|
||||
pci_stop_and_remove_bus_device(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
pci_unlock_rescan_remove();
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user