diff options
author | Taku Izumi <izumi.taku@jp.fujitsu.com> | 2012-09-18 10:21:31 +0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2012-09-25 01:29:40 +0400 |
commit | d0020f65220c237f300355873125df5efe2c2740 (patch) | |
tree | 8ab5df845900638034f30daf2b78d33c0924223b | |
parent | c8e9afb124f61e0c9901801f4c95ae4208bd4536 (diff) | |
download | linux-d0020f65220c237f300355873125df5efe2c2740.tar.xz |
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 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/types.h> -#include <linux/spinlock.h> +#include <linux/mutex.h> #include <linux/pm.h> #include <linux/pm_runtime.h> #include <linux/pci.h> @@ -71,6 +71,8 @@ static struct acpi_driver acpi_pci_root_driver = { }, }; +/* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ +static DEFINE_MUTEX(acpi_pci_root_lock); static LIST_HEAD(acpi_pci_roots); static LIST_HEAD(acpi_pci_drivers); @@ -81,34 +83,30 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver) int n = 0; struct acpi_pci_root *root; + mutex_lock(&acpi_pci_root_lock); list_add_tail(&driver->node, &acpi_pci_drivers); - - if (!driver->add) - return 0; - - list_for_each_entry(root, &acpi_pci_roots, node) { - driver->add(root->device->handle); - n++; - } + if (driver->add) + list_for_each_entry(root, &acpi_pci_roots, node) { + driver->add(root->device->handle); + n++; + } + mutex_unlock(&acpi_pci_root_lock); return n; } - EXPORT_SYMBOL(acpi_pci_register_driver); void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) { struct acpi_pci_root *root; + mutex_lock(&acpi_pci_root_lock); list_del(&driver->node); - - if (!driver->remove) - return; - - list_for_each_entry(root, &acpi_pci_roots, node) - driver->remove(root->device->handle); + if (driver->remove) + list_for_each_entry(root, &acpi_pci_roots, node) + driver->remove(root->device->handle); + mutex_unlock(&acpi_pci_root_lock); } - EXPORT_SYMBOL(acpi_pci_unregister_driver); 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) struct acpi_pci_root *root = acpi_driver_data(device); struct acpi_pci_driver *driver; + mutex_lock(&acpi_pci_root_lock); list_for_each_entry(driver, &acpi_pci_drivers, node) if (driver->add) driver->add(device->handle); + mutex_unlock(&acpi_pci_root_lock); pci_bus_add_devices(root->bus); @@ -642,9 +642,11 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) struct acpi_pci_root *root = acpi_driver_data(device); struct acpi_pci_driver *driver; + mutex_lock(&acpi_pci_root_lock); list_for_each_entry(driver, &acpi_pci_drivers, node) if (driver->remove) driver->remove(root->device->handle); + mutex_unlock(&acpi_pci_root_lock); device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); |