aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/pci.h
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-01-10 09:22:18 -0500
committerBjorn Helgaas <bhelgaas@google.com>2014-01-13 19:49:49 -0500
commit9d16947b75831acd317ab9a53e0e94d160731d33 (patch)
tree6eeee1ae3a6864ceaae7ba60e7abc846f1acb0a9 /include/linux/pci.h
parenta870614a5371f8e36676e9bb2e089f4121976135 (diff)
PCI: Add global pci_lock_rescan_remove()
There are multiple PCI device addition and removal code paths that may be run concurrently with the generic PCI bus rescan and device removal that can be triggered via sysfs. If that happens, it may lead to multiple different, potentially dangerous race conditions. The most straightforward way to address those problems is to run the code in question under the same lock that is used by the generic rescan/remove code in pci-sysfs.c. To prepare for those changes, move the definition of the global PCI remove/rescan lock to probe.c and provide global wrappers, pci_lock_rescan_remove() and pci_unlock_rescan_remove(), allowing drivers to manipulate that lock. Also provide pci_stop_and_remove_bus_device_locked() for the callers of pci_stop_and_remove_bus_device() who only need to hold the rescan/remove lock around it. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'include/linux/pci.h')
-rw-r--r--include/linux/pci.h3
1 files changed, 3 insertions, 0 deletions
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 9e3ec8b951b7..2087e6b35545 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -775,6 +775,7 @@ struct pci_dev *pci_dev_get(struct pci_dev *dev);
775void pci_dev_put(struct pci_dev *dev); 775void pci_dev_put(struct pci_dev *dev);
776void pci_remove_bus(struct pci_bus *b); 776void pci_remove_bus(struct pci_bus *b);
777void pci_stop_and_remove_bus_device(struct pci_dev *dev); 777void pci_stop_and_remove_bus_device(struct pci_dev *dev);
778void pci_stop_and_remove_bus_device_locked(struct pci_dev *dev);
778void pci_stop_root_bus(struct pci_bus *bus); 779void pci_stop_root_bus(struct pci_bus *bus);
779void pci_remove_root_bus(struct pci_bus *bus); 780void pci_remove_root_bus(struct pci_bus *bus);
780void pci_setup_cardbus(struct pci_bus *bus); 781void pci_setup_cardbus(struct pci_bus *bus);
@@ -1011,6 +1012,8 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev);
1011int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap); 1012int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap);
1012unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge); 1013unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge);
1013unsigned int pci_rescan_bus(struct pci_bus *bus); 1014unsigned int pci_rescan_bus(struct pci_bus *bus);
1015void pci_lock_rescan_remove(void);
1016void pci_unlock_rescan_remove(void);
1014 1017
1015/* Vital product data routines */ 1018/* Vital product data routines */
1016ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf); 1019ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf);