diff options
author | Taku Izumi <izumi.taku@jp.fujitsu.com> | 2012-09-18 02:21:31 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2012-09-24 17:29:40 -0400 |
commit | d0020f65220c237f300355873125df5efe2c2740 (patch) | |
tree | 8ab5df845900638034f30daf2b78d33c0924223b | |
parent | c8e9afb124f61e0c9901801f4c95ae4208bd4536 (diff) |
PCI/ACPI: Protect acpi_pci_drivers list with mutex
Use mutex to protect global acpi_pci_drivers list against PCI
host bridge hotplug operations.
Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r-- | drivers/acpi/pci_root.c | 36 |
1 files changed, 19 insertions, 17 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 4bec13d9c2bf..d710585e4a7f 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
30 | #include <linux/spinlock.h> | 30 | #include <linux/mutex.h> |
31 | #include <linux/pm.h> | 31 | #include <linux/pm.h> |
32 | #include <linux/pm_runtime.h> | 32 | #include <linux/pm_runtime.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
@@ -71,6 +71,8 @@ static struct acpi_driver acpi_pci_root_driver = { | |||
71 | }, | 71 | }, |
72 | }; | 72 | }; |
73 | 73 | ||
74 | /* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ | ||
75 | static DEFINE_MUTEX(acpi_pci_root_lock); | ||
74 | static LIST_HEAD(acpi_pci_roots); | 76 | static LIST_HEAD(acpi_pci_roots); |
75 | static LIST_HEAD(acpi_pci_drivers); | 77 | static LIST_HEAD(acpi_pci_drivers); |
76 | 78 | ||
@@ -81,34 +83,30 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver) | |||
81 | int n = 0; | 83 | int n = 0; |
82 | struct acpi_pci_root *root; | 84 | struct acpi_pci_root *root; |
83 | 85 | ||
86 | mutex_lock(&acpi_pci_root_lock); | ||
84 | list_add_tail(&driver->node, &acpi_pci_drivers); | 87 | list_add_tail(&driver->node, &acpi_pci_drivers); |
85 | 88 | if (driver->add) | |
86 | if (!driver->add) | 89 | list_for_each_entry(root, &acpi_pci_roots, node) { |
87 | return 0; | 90 | driver->add(root->device->handle); |
88 | 91 | n++; | |
89 | list_for_each_entry(root, &acpi_pci_roots, node) { | 92 | } |
90 | driver->add(root->device->handle); | 93 | mutex_unlock(&acpi_pci_root_lock); |
91 | n++; | ||
92 | } | ||
93 | 94 | ||
94 | return n; | 95 | return n; |
95 | } | 96 | } |
96 | |||
97 | EXPORT_SYMBOL(acpi_pci_register_driver); | 97 | EXPORT_SYMBOL(acpi_pci_register_driver); |
98 | 98 | ||
99 | void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) | 99 | void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) |
100 | { | 100 | { |
101 | struct acpi_pci_root *root; | 101 | struct acpi_pci_root *root; |
102 | 102 | ||
103 | mutex_lock(&acpi_pci_root_lock); | ||
103 | list_del(&driver->node); | 104 | list_del(&driver->node); |
104 | 105 | if (driver->remove) | |
105 | if (!driver->remove) | 106 | list_for_each_entry(root, &acpi_pci_roots, node) |
106 | return; | 107 | driver->remove(root->device->handle); |
107 | 108 | mutex_unlock(&acpi_pci_root_lock); | |
108 | list_for_each_entry(root, &acpi_pci_roots, node) | ||
109 | driver->remove(root->device->handle); | ||
110 | } | 109 | } |
111 | |||
112 | EXPORT_SYMBOL(acpi_pci_unregister_driver); | 110 | EXPORT_SYMBOL(acpi_pci_unregister_driver); |
113 | 111 | ||
114 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) | 112 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) |
@@ -628,9 +626,11 @@ static int acpi_pci_root_start(struct acpi_device *device) | |||
628 | struct acpi_pci_root *root = acpi_driver_data(device); | 626 | struct acpi_pci_root *root = acpi_driver_data(device); |
629 | struct acpi_pci_driver *driver; | 627 | struct acpi_pci_driver *driver; |
630 | 628 | ||
629 | mutex_lock(&acpi_pci_root_lock); | ||
631 | list_for_each_entry(driver, &acpi_pci_drivers, node) | 630 | list_for_each_entry(driver, &acpi_pci_drivers, node) |
632 | if (driver->add) | 631 | if (driver->add) |
633 | driver->add(device->handle); | 632 | driver->add(device->handle); |
633 | mutex_unlock(&acpi_pci_root_lock); | ||
634 | 634 | ||
635 | pci_bus_add_devices(root->bus); | 635 | pci_bus_add_devices(root->bus); |
636 | 636 | ||
@@ -642,9 +642,11 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) | |||
642 | struct acpi_pci_root *root = acpi_driver_data(device); | 642 | struct acpi_pci_root *root = acpi_driver_data(device); |
643 | struct acpi_pci_driver *driver; | 643 | struct acpi_pci_driver *driver; |
644 | 644 | ||
645 | mutex_lock(&acpi_pci_root_lock); | ||
645 | list_for_each_entry(driver, &acpi_pci_drivers, node) | 646 | list_for_each_entry(driver, &acpi_pci_drivers, node) |
646 | if (driver->remove) | 647 | if (driver->remove) |
647 | driver->remove(root->device->handle); | 648 | driver->remove(root->device->handle); |
649 | mutex_unlock(&acpi_pci_root_lock); | ||
648 | 650 | ||
649 | device_set_run_wake(root->bus->bridge, false); | 651 | device_set_run_wake(root->bus->bridge, false); |
650 | pci_acpi_remove_bus_pm_notifier(device); | 652 | pci_acpi_remove_bus_pm_notifier(device); |