aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-01-10 09:29:19 -0500
committerBjorn Helgaas <bhelgaas@google.com>2014-01-15 12:34:13 -0500
commita83919e0940f6eb8f77ab1d602a063f8a6703117 (patch)
treedacfd74f6352ed42744ebfcaff6ff4c987919c49 /drivers
parent1c2042c83aa7af10579b71a1fe5e22bbae69f08c (diff)
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')
-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,
471 } 471 }
472 pcifront_init_sd(sd, domain, bus, pdev); 472 pcifront_init_sd(sd, domain, bus, pdev);
473 473
474 pci_lock_rescan_remove();
475
474 b = pci_scan_bus_parented(&pdev->xdev->dev, bus, 476 b = pci_scan_bus_parented(&pdev->xdev->dev, bus,
475 &pcifront_bus_ops, sd); 477 &pcifront_bus_ops, sd);
476 if (!b) { 478 if (!b) {
477 dev_err(&pdev->xdev->dev, 479 dev_err(&pdev->xdev->dev,
478 "Error creating PCI Frontend Bus!\n"); 480 "Error creating PCI Frontend Bus!\n");
479 err = -ENOMEM; 481 err = -ENOMEM;
482 pci_unlock_rescan_remove();
480 goto err_out; 483 goto err_out;
481 } 484 }
482 485
@@ -494,6 +497,7 @@ static int pcifront_scan_root(struct pcifront_device *pdev,
494 /* Create SysFS and notify udev of the devices. Aka: "going live" */ 497 /* Create SysFS and notify udev of the devices. Aka: "going live" */
495 pci_bus_add_devices(b); 498 pci_bus_add_devices(b);
496 499
500 pci_unlock_rescan_remove();
497 return err; 501 return err;
498 502
499err_out: 503err_out:
@@ -556,6 +560,7 @@ static void pcifront_free_roots(struct pcifront_device *pdev)
556 560
557 dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n"); 561 dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n");
558 562
563 pci_lock_rescan_remove();
559 list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) { 564 list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) {
560 list_del(&bus_entry->list); 565 list_del(&bus_entry->list);
561 566
@@ -568,6 +573,7 @@ static void pcifront_free_roots(struct pcifront_device *pdev)
568 573
569 kfree(bus_entry); 574 kfree(bus_entry);
570 } 575 }
576 pci_unlock_rescan_remove();
571} 577}
572 578
573static pci_ers_result_t pcifront_common_process(int cmd, 579static pci_ers_result_t pcifront_common_process(int cmd,
@@ -1043,8 +1049,10 @@ static int pcifront_detach_devices(struct pcifront_device *pdev)
1043 domain, bus, slot, func); 1049 domain, bus, slot, func);
1044 continue; 1050 continue;
1045 } 1051 }
1052 pci_lock_rescan_remove();
1046 pci_stop_and_remove_bus_device(pci_dev); 1053 pci_stop_and_remove_bus_device(pci_dev);
1047 pci_dev_put(pci_dev); 1054 pci_dev_put(pci_dev);
1055 pci_unlock_rescan_remove();
1048 1056
1049 dev_dbg(&pdev->xdev->dev, 1057 dev_dbg(&pdev->xdev->dev,
1050 "PCI device %04x:%02x:%02x.%d removed.\n", 1058 "PCI device %04x:%02x:%02x.%d removed.\n",