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 /drivers/acpi | |
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>
Diffstat (limited to 'drivers/acpi')
-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 | } |