aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/pci_root.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/pci_root.c')
-rw-r--r--drivers/acpi/pci_root.c101
1 files changed, 58 insertions, 43 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 72a2c98bc429..bce469c0b48a 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,9 +71,11 @@ 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 */
75static DEFINE_MUTEX(acpi_pci_root_lock);
74static LIST_HEAD(acpi_pci_roots); 76static LIST_HEAD(acpi_pci_roots);
77static LIST_HEAD(acpi_pci_drivers);
75 78
76static struct acpi_pci_driver *sub_driver;
77static DEFINE_MUTEX(osc_lock); 79static DEFINE_MUTEX(osc_lock);
78 80
79int acpi_pci_register_driver(struct acpi_pci_driver *driver) 81int acpi_pci_register_driver(struct acpi_pci_driver *driver)
@@ -81,55 +83,46 @@ 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
84 struct acpi_pci_driver **pptr = &sub_driver; 86 mutex_lock(&acpi_pci_root_lock);
85 while (*pptr) 87 list_add_tail(&driver->node, &acpi_pci_drivers);
86 pptr = &(*pptr)->next; 88 if (driver->add)
87 *pptr = driver; 89 list_for_each_entry(root, &acpi_pci_roots, node) {
88 90 driver->add(root);
89 if (!driver->add) 91 n++;
90 return 0; 92 }
91 93 mutex_unlock(&acpi_pci_root_lock);
92 list_for_each_entry(root, &acpi_pci_roots, node) {
93 driver->add(root->device->handle);
94 n++;
95 }
96 94
97 return n; 95 return n;
98} 96}
99
100EXPORT_SYMBOL(acpi_pci_register_driver); 97EXPORT_SYMBOL(acpi_pci_register_driver);
101 98
102void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) 99void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
103{ 100{
104 struct acpi_pci_root *root; 101 struct acpi_pci_root *root;
105 102
106 struct acpi_pci_driver **pptr = &sub_driver; 103 mutex_lock(&acpi_pci_root_lock);
107 while (*pptr) { 104 list_del(&driver->node);
108 if (*pptr == driver) 105 if (driver->remove)
109 break; 106 list_for_each_entry(root, &acpi_pci_roots, node)
110 pptr = &(*pptr)->next; 107 driver->remove(root);
111 } 108 mutex_unlock(&acpi_pci_root_lock);
112 BUG_ON(!*pptr);
113 *pptr = (*pptr)->next;
114
115 if (!driver->remove)
116 return;
117
118 list_for_each_entry(root, &acpi_pci_roots, node)
119 driver->remove(root->device->handle);
120} 109}
121
122EXPORT_SYMBOL(acpi_pci_unregister_driver); 110EXPORT_SYMBOL(acpi_pci_unregister_driver);
123 111
124acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) 112acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus)
125{ 113{
126 struct acpi_pci_root *root; 114 struct acpi_pci_root *root;
115 acpi_handle handle = NULL;
127 116
117 mutex_lock(&acpi_pci_root_lock);
128 list_for_each_entry(root, &acpi_pci_roots, node) 118 list_for_each_entry(root, &acpi_pci_roots, node)
129 if ((root->segment == (u16) seg) && 119 if ((root->segment == (u16) seg) &&
130 (root->secondary.start == (u16) bus)) 120 (root->secondary.start == (u16) bus)) {
131 return root->device->handle; 121 handle = root->device->handle;
132 return NULL; 122 break;
123 }
124 mutex_unlock(&acpi_pci_root_lock);
125 return handle;
133} 126}
134 127
135EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); 128EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle);
@@ -277,12 +270,15 @@ static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags)
277struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) 270struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle)
278{ 271{
279 struct acpi_pci_root *root; 272 struct acpi_pci_root *root;
273 struct acpi_device *device;
280 274
281 list_for_each_entry(root, &acpi_pci_roots, node) { 275 if (acpi_bus_get_device(handle, &device) ||
282 if (root->device->handle == handle) 276 acpi_match_device_ids(device, root_device_ids))
283 return root; 277 return NULL;
284 } 278
285 return NULL; 279 root = acpi_driver_data(device);
280
281 return root;
286} 282}
287EXPORT_SYMBOL_GPL(acpi_pci_find_root); 283EXPORT_SYMBOL_GPL(acpi_pci_find_root);
288 284
@@ -518,8 +514,9 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
518 * TBD: Need PCI interface for enumeration/configuration of roots. 514 * TBD: Need PCI interface for enumeration/configuration of roots.
519 */ 515 */
520 516
521 /* TBD: Locking */ 517 mutex_lock(&acpi_pci_root_lock);
522 list_add_tail(&root->node, &acpi_pci_roots); 518 list_add_tail(&root->node, &acpi_pci_roots);
519 mutex_unlock(&acpi_pci_root_lock);
523 520
524 printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", 521 printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
525 acpi_device_name(device), acpi_device_bid(device), 522 acpi_device_name(device), acpi_device_bid(device),
@@ -538,7 +535,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
538 "Bus %04x:%02x not present in PCI namespace\n", 535 "Bus %04x:%02x not present in PCI namespace\n",
539 root->segment, (unsigned int)root->secondary.start); 536 root->segment, (unsigned int)root->secondary.start);
540 result = -ENODEV; 537 result = -ENODEV;
541 goto end; 538 goto out_del_root;
542 } 539 }
543 540
544 /* 541 /*
@@ -548,7 +545,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
548 */ 545 */
549 result = acpi_pci_bind_root(device); 546 result = acpi_pci_bind_root(device);
550 if (result) 547 if (result)
551 goto end; 548 goto out_del_root;
552 549
553 /* 550 /*
554 * PCI Routing Table 551 * PCI Routing Table
@@ -633,9 +630,11 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
633 630
634 return 0; 631 return 0;
635 632
633out_del_root:
634 mutex_lock(&acpi_pci_root_lock);
635 list_del(&root->node);
636 mutex_unlock(&acpi_pci_root_lock);
636end: 637end:
637 if (!list_empty(&root->node))
638 list_del(&root->node);
639 kfree(root); 638 kfree(root);
640 return result; 639 return result;
641} 640}
@@ -643,18 +642,34 @@ end:
643static int acpi_pci_root_start(struct acpi_device *device) 642static int acpi_pci_root_start(struct acpi_device *device)
644{ 643{
645 struct acpi_pci_root *root = acpi_driver_data(device); 644 struct acpi_pci_root *root = acpi_driver_data(device);
645 struct acpi_pci_driver *driver;
646
647 mutex_lock(&acpi_pci_root_lock);
648 list_for_each_entry(driver, &acpi_pci_drivers, node)
649 if (driver->add)
650 driver->add(root);
651 mutex_unlock(&acpi_pci_root_lock);
646 652
647 pci_bus_add_devices(root->bus); 653 pci_bus_add_devices(root->bus);
654
648 return 0; 655 return 0;
649} 656}
650 657
651static int acpi_pci_root_remove(struct acpi_device *device, int type) 658static int acpi_pci_root_remove(struct acpi_device *device, int type)
652{ 659{
653 struct acpi_pci_root *root = acpi_driver_data(device); 660 struct acpi_pci_root *root = acpi_driver_data(device);
661 struct acpi_pci_driver *driver;
662
663 mutex_lock(&acpi_pci_root_lock);
664 list_for_each_entry(driver, &acpi_pci_drivers, node)
665 if (driver->remove)
666 driver->remove(root);
654 667
655 device_set_run_wake(root->bus->bridge, false); 668 device_set_run_wake(root->bus->bridge, false);
656 pci_acpi_remove_bus_pm_notifier(device); 669 pci_acpi_remove_bus_pm_notifier(device);
657 670
671 list_del(&root->node);
672 mutex_unlock(&acpi_pci_root_lock);
658 kfree(root); 673 kfree(root);
659 return 0; 674 return 0;
660} 675}