summaryrefslogtreecommitdiff
path: root/drivers/acpi/pci_root.c
diff options
context:
space:
mode:
authorTaku Izumi <izumi.taku@jp.fujitsu.com>2012-09-18 15:24:40 +0900
committerBjorn Helgaas <bhelgaas@google.com>2012-09-24 15:29:40 -0600
commit6507e6ebebd2d5f7e17c6f2e32524270edd2a922 (patch)
tree114d7ae45260843d316040f3c7715b4ef1ae1919 /drivers/acpi/pci_root.c
parent0f2bdfedcb8f1aaf54a0ab4934f33b3710692a19 (diff)
downloadlwn-6507e6ebebd2d5f7e17c6f2e32524270edd2a922.tar.gz
lwn-6507e6ebebd2d5f7e17c6f2e32524270edd2a922.zip
PCI/ACPI: Protect acpi_pci_roots list with mutex
Use mutex to protect acpi_pci_roots list against PCI host bridge hotplug operations. [bhelgaas: s/struct acpi_handle *handle/acpi_handle handle/] Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/acpi/pci_root.c')
-rw-r--r--drivers/acpi/pci_root.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 2868a9ff6d07..e1bdcc700cbb 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -112,12 +112,17 @@ EXPORT_SYMBOL(acpi_pci_unregister_driver);
acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus)
{
struct acpi_pci_root *root;
+ acpi_handle handle = NULL;
+ mutex_lock(&acpi_pci_root_lock);
list_for_each_entry(root, &acpi_pci_roots, node)
if ((root->segment == (u16) seg) &&
- (root->secondary.start == (u16) bus))
- return root->device->handle;
- return NULL;
+ (root->secondary.start == (u16) bus)) {
+ handle = root->device->handle;
+ break;
+ }
+ mutex_unlock(&acpi_pci_root_lock);
+ return handle;
}
EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle);
@@ -506,8 +511,9 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
* TBD: Need PCI interface for enumeration/configuration of roots.
*/
- /* TBD: Locking */
+ mutex_lock(&acpi_pci_root_lock);
list_add_tail(&root->node, &acpi_pci_roots);
+ mutex_unlock(&acpi_pci_root_lock);
printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
acpi_device_name(device), acpi_device_bid(device),
@@ -526,7 +532,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
"Bus %04x:%02x not present in PCI namespace\n",
root->segment, (unsigned int)root->secondary.start);
result = -ENODEV;
- goto end;
+ goto out_del_root;
}
/*
@@ -536,7 +542,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
*/
result = acpi_pci_bind_root(device);
if (result)
- goto end;
+ goto out_del_root;
/*
* PCI Routing Table
@@ -614,9 +620,11 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
return 0;
+out_del_root:
+ mutex_lock(&acpi_pci_root_lock);
+ list_del(&root->node);
+ mutex_unlock(&acpi_pci_root_lock);
end:
- if (!list_empty(&root->node))
- list_del(&root->node);
kfree(root);
return result;
}
@@ -646,11 +654,12 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
list_for_each_entry(driver, &acpi_pci_drivers, node)
if (driver->remove)
driver->remove(root);
- mutex_unlock(&acpi_pci_root_lock);
device_set_run_wake(root->bus->bridge, false);
pci_acpi_remove_bus_pm_notifier(device);
+ list_del(&root->node);
+ mutex_unlock(&acpi_pci_root_lock);
kfree(root);
return 0;
}