diff options
| author | Taku Izumi <izumi.taku@jp.fujitsu.com> | 2012-09-18 02:24:40 -0400 |
|---|---|---|
| committer | Bjorn Helgaas <bhelgaas@google.com> | 2012-09-24 17:29:40 -0400 |
| commit | 6507e6ebebd2d5f7e17c6f2e32524270edd2a922 (patch) | |
| tree | 114d7ae45260843d316040f3c7715b4ef1ae1919 | |
| parent | 0f2bdfedcb8f1aaf54a0ab4934f33b3710692a19 (diff) | |
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>
| -rw-r--r-- | drivers/acpi/pci_root.c | 27 |
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); | |||
| 112 | 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) |
| 113 | { | 113 | { |
| 114 | struct acpi_pci_root *root; | 114 | struct acpi_pci_root *root; |
| 115 | acpi_handle handle = NULL; | ||
| 115 | 116 | ||
| 117 | mutex_lock(&acpi_pci_root_lock); | ||
| 116 | list_for_each_entry(root, &acpi_pci_roots, node) | 118 | list_for_each_entry(root, &acpi_pci_roots, node) |
| 117 | if ((root->segment == (u16) seg) && | 119 | if ((root->segment == (u16) seg) && |
| 118 | (root->secondary.start == (u16) bus)) | 120 | (root->secondary.start == (u16) bus)) { |
| 119 | return root->device->handle; | 121 | handle = root->device->handle; |
| 120 | return NULL; | 122 | break; |
| 123 | } | ||
| 124 | mutex_unlock(&acpi_pci_root_lock); | ||
| 125 | return handle; | ||
| 121 | } | 126 | } |
| 122 | 127 | ||
| 123 | EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); | 128 | EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); |
| @@ -506,8 +511,9 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 506 | * TBD: Need PCI interface for enumeration/configuration of roots. | 511 | * TBD: Need PCI interface for enumeration/configuration of roots. |
| 507 | */ | 512 | */ |
| 508 | 513 | ||
| 509 | /* TBD: Locking */ | 514 | mutex_lock(&acpi_pci_root_lock); |
| 510 | list_add_tail(&root->node, &acpi_pci_roots); | 515 | list_add_tail(&root->node, &acpi_pci_roots); |
| 516 | mutex_unlock(&acpi_pci_root_lock); | ||
| 511 | 517 | ||
| 512 | printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", | 518 | printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", |
| 513 | acpi_device_name(device), acpi_device_bid(device), | 519 | acpi_device_name(device), acpi_device_bid(device), |
| @@ -526,7 +532,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 526 | "Bus %04x:%02x not present in PCI namespace\n", | 532 | "Bus %04x:%02x not present in PCI namespace\n", |
| 527 | root->segment, (unsigned int)root->secondary.start); | 533 | root->segment, (unsigned int)root->secondary.start); |
| 528 | result = -ENODEV; | 534 | result = -ENODEV; |
| 529 | goto end; | 535 | goto out_del_root; |
| 530 | } | 536 | } |
| 531 | 537 | ||
| 532 | /* | 538 | /* |
| @@ -536,7 +542,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 536 | */ | 542 | */ |
| 537 | result = acpi_pci_bind_root(device); | 543 | result = acpi_pci_bind_root(device); |
| 538 | if (result) | 544 | if (result) |
| 539 | goto end; | 545 | goto out_del_root; |
| 540 | 546 | ||
| 541 | /* | 547 | /* |
| 542 | * PCI Routing Table | 548 | * PCI Routing Table |
| @@ -614,9 +620,11 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 614 | 620 | ||
| 615 | return 0; | 621 | return 0; |
| 616 | 622 | ||
| 623 | out_del_root: | ||
| 624 | mutex_lock(&acpi_pci_root_lock); | ||
| 625 | list_del(&root->node); | ||
| 626 | mutex_unlock(&acpi_pci_root_lock); | ||
| 617 | end: | 627 | end: |
| 618 | if (!list_empty(&root->node)) | ||
| 619 | list_del(&root->node); | ||
| 620 | kfree(root); | 628 | kfree(root); |
| 621 | return result; | 629 | return result; |
| 622 | } | 630 | } |
| @@ -646,11 +654,12 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) | |||
| 646 | list_for_each_entry(driver, &acpi_pci_drivers, node) | 654 | list_for_each_entry(driver, &acpi_pci_drivers, node) |
| 647 | if (driver->remove) | 655 | if (driver->remove) |
| 648 | driver->remove(root); | 656 | driver->remove(root); |
| 649 | mutex_unlock(&acpi_pci_root_lock); | ||
| 650 | 657 | ||
| 651 | device_set_run_wake(root->bus->bridge, false); | 658 | device_set_run_wake(root->bus->bridge, false); |
| 652 | pci_acpi_remove_bus_pm_notifier(device); | 659 | pci_acpi_remove_bus_pm_notifier(device); |
| 653 | 660 | ||
| 661 | list_del(&root->node); | ||
| 662 | mutex_unlock(&acpi_pci_root_lock); | ||
| 654 | kfree(root); | 663 | kfree(root); |
| 655 | return 0; | 664 | return 0; |
| 656 | } | 665 | } |
