summaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-01-10 15:29:19 +0100
committerBjorn Helgaas <bhelgaas@google.com>2014-01-15 18:34:13 +0100
commita83919e0940f6eb8f77ab1d602a063f8a6703117 (patch)
treedacfd74f6352ed42744ebfcaff6ff4c987919c49 /drivers/pci
parentpowerpc/eeh: Use global PCI rescan-remove locking (diff)
downloadlinux-a83919e0940f6eb8f77ab1d602a063f8a6703117.tar.xz
linux-a83919e0940f6eb8f77ab1d602a063f8a6703117.zip
xen/pcifront: Use global PCI rescan-remove locking
Multiple race conditions are possible between the Xen pcifront device addition and removal and the generic PCI device addition and removal that can be triggered via sysfs. To avoid those race conditions make the Xen pcifront code 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>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/xen-pcifront.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index f7197a790341..d1cd60f51f87 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -471,12 +471,15 @@ static int pcifront_scan_root(struct pcifront_device *pdev,
}
pcifront_init_sd(sd, domain, bus, pdev);
+ pci_lock_rescan_remove();
+
b = pci_scan_bus_parented(&pdev->xdev->dev, bus,
&pcifront_bus_ops, sd);
if (!b) {
dev_err(&pdev->xdev->dev,
"Error creating PCI Frontend Bus!\n");
err = -ENOMEM;
+ pci_unlock_rescan_remove();
goto err_out;
}
@@ -494,6 +497,7 @@ static int pcifront_scan_root(struct pcifront_device *pdev,
/* Create SysFS and notify udev of the devices. Aka: "going live" */
pci_bus_add_devices(b);
+ pci_unlock_rescan_remove();
return err;
err_out:
@@ -556,6 +560,7 @@ static void pcifront_free_roots(struct pcifront_device *pdev)
dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n");
+ pci_lock_rescan_remove();
list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) {
list_del(&bus_entry->list);
@@ -568,6 +573,7 @@ static void pcifront_free_roots(struct pcifront_device *pdev)
kfree(bus_entry);
}
+ pci_unlock_rescan_remove();
}
static pci_ers_result_t pcifront_common_process(int cmd,
@@ -1043,8 +1049,10 @@ static int pcifront_detach_devices(struct pcifront_device *pdev)
domain, bus, slot, func);
continue;
}
+ pci_lock_rescan_remove();
pci_stop_and_remove_bus_device(pci_dev);
pci_dev_put(pci_dev);
+ pci_unlock_rescan_remove();
dev_dbg(&pdev->xdev->dev,
"PCI device %04x:%02x:%02x.%d removed.\n",