diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pci-sysfs.c | 19 | ||||
-rw-r--r-- | drivers/pci/probe.c | 18 | ||||
-rw-r--r-- | drivers/pci/remove.c | 8 |
3 files changed, 33 insertions, 12 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index c91e6c18debc..276ef9c18802 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -297,7 +297,6 @@ msi_bus_store(struct device *dev, struct device_attribute *attr, | |||
297 | } | 297 | } |
298 | static DEVICE_ATTR_RW(msi_bus); | 298 | static DEVICE_ATTR_RW(msi_bus); |
299 | 299 | ||
300 | static DEFINE_MUTEX(pci_remove_rescan_mutex); | ||
301 | static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf, | 300 | static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf, |
302 | size_t count) | 301 | size_t count) |
303 | { | 302 | { |
@@ -308,10 +307,10 @@ static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf, | |||
308 | return -EINVAL; | 307 | return -EINVAL; |
309 | 308 | ||
310 | if (val) { | 309 | if (val) { |
311 | mutex_lock(&pci_remove_rescan_mutex); | 310 | pci_lock_rescan_remove(); |
312 | while ((b = pci_find_next_bus(b)) != NULL) | 311 | while ((b = pci_find_next_bus(b)) != NULL) |
313 | pci_rescan_bus(b); | 312 | pci_rescan_bus(b); |
314 | mutex_unlock(&pci_remove_rescan_mutex); | 313 | pci_unlock_rescan_remove(); |
315 | } | 314 | } |
316 | return count; | 315 | return count; |
317 | } | 316 | } |
@@ -342,9 +341,9 @@ dev_rescan_store(struct device *dev, struct device_attribute *attr, | |||
342 | return -EINVAL; | 341 | return -EINVAL; |
343 | 342 | ||
344 | if (val) { | 343 | if (val) { |
345 | mutex_lock(&pci_remove_rescan_mutex); | 344 | pci_lock_rescan_remove(); |
346 | pci_rescan_bus(pdev->bus); | 345 | pci_rescan_bus(pdev->bus); |
347 | mutex_unlock(&pci_remove_rescan_mutex); | 346 | pci_unlock_rescan_remove(); |
348 | } | 347 | } |
349 | return count; | 348 | return count; |
350 | } | 349 | } |
@@ -354,11 +353,7 @@ static struct device_attribute dev_rescan_attr = __ATTR(rescan, | |||
354 | 353 | ||
355 | static void remove_callback(struct device *dev) | 354 | static void remove_callback(struct device *dev) |
356 | { | 355 | { |
357 | struct pci_dev *pdev = to_pci_dev(dev); | 356 | pci_stop_and_remove_bus_device_locked(to_pci_dev(dev)); |
358 | |||
359 | mutex_lock(&pci_remove_rescan_mutex); | ||
360 | pci_stop_and_remove_bus_device(pdev); | ||
361 | mutex_unlock(&pci_remove_rescan_mutex); | ||
362 | } | 357 | } |
363 | 358 | ||
364 | static ssize_t | 359 | static ssize_t |
@@ -395,12 +390,12 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr, | |||
395 | return -EINVAL; | 390 | return -EINVAL; |
396 | 391 | ||
397 | if (val) { | 392 | if (val) { |
398 | mutex_lock(&pci_remove_rescan_mutex); | 393 | pci_lock_rescan_remove(); |
399 | if (!pci_is_root_bus(bus) && list_empty(&bus->devices)) | 394 | if (!pci_is_root_bus(bus) && list_empty(&bus->devices)) |
400 | pci_rescan_bus_bridge_resize(bus->self); | 395 | pci_rescan_bus_bridge_resize(bus->self); |
401 | else | 396 | else |
402 | pci_rescan_bus(bus); | 397 | pci_rescan_bus(bus); |
403 | mutex_unlock(&pci_remove_rescan_mutex); | 398 | pci_unlock_rescan_remove(); |
404 | } | 399 | } |
405 | return count; | 400 | return count; |
406 | } | 401 | } |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index c86c8638d3c4..04796c056d12 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -2024,6 +2024,24 @@ EXPORT_SYMBOL(pci_scan_slot); | |||
2024 | EXPORT_SYMBOL(pci_scan_bridge); | 2024 | EXPORT_SYMBOL(pci_scan_bridge); |
2025 | EXPORT_SYMBOL_GPL(pci_scan_child_bus); | 2025 | EXPORT_SYMBOL_GPL(pci_scan_child_bus); |
2026 | 2026 | ||
2027 | /* | ||
2028 | * pci_rescan_bus(), pci_rescan_bus_bridge_resize() and PCI device removal | ||
2029 | * routines should always be executed under this mutex. | ||
2030 | */ | ||
2031 | static DEFINE_MUTEX(pci_rescan_remove_lock); | ||
2032 | |||
2033 | void pci_lock_rescan_remove(void) | ||
2034 | { | ||
2035 | mutex_lock(&pci_rescan_remove_lock); | ||
2036 | } | ||
2037 | EXPORT_SYMBOL_GPL(pci_lock_rescan_remove); | ||
2038 | |||
2039 | void pci_unlock_rescan_remove(void) | ||
2040 | { | ||
2041 | mutex_unlock(&pci_rescan_remove_lock); | ||
2042 | } | ||
2043 | EXPORT_SYMBOL_GPL(pci_unlock_rescan_remove); | ||
2044 | |||
2027 | static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b) | 2045 | static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b) |
2028 | { | 2046 | { |
2029 | const struct pci_dev *a = to_pci_dev(d_a); | 2047 | const struct pci_dev *a = to_pci_dev(d_a); |
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index f452148e6d55..10fa13f9e309 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c | |||
@@ -95,6 +95,14 @@ void pci_stop_and_remove_bus_device(struct pci_dev *dev) | |||
95 | } | 95 | } |
96 | EXPORT_SYMBOL(pci_stop_and_remove_bus_device); | 96 | EXPORT_SYMBOL(pci_stop_and_remove_bus_device); |
97 | 97 | ||
98 | void pci_stop_and_remove_bus_device_locked(struct pci_dev *dev) | ||
99 | { | ||
100 | pci_lock_rescan_remove(); | ||
101 | pci_stop_and_remove_bus_device(dev); | ||
102 | pci_unlock_rescan_remove(); | ||
103 | } | ||
104 | EXPORT_SYMBOL_GPL(pci_stop_and_remove_bus_device_locked); | ||
105 | |||
98 | void pci_stop_root_bus(struct pci_bus *bus) | 106 | void pci_stop_root_bus(struct pci_bus *bus) |
99 | { | 107 | { |
100 | struct pci_dev *child, *tmp; | 108 | struct pci_dev *child, *tmp; |