aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/pci_root.c101
-rw-r--r--drivers/acpi/pci_slot.c44
2 files changed, 68 insertions, 77 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}
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
index e50e31a518af..d22585f21aeb 100644
--- a/drivers/acpi/pci_slot.c
+++ b/drivers/acpi/pci_slot.c
@@ -67,8 +67,8 @@ struct acpi_pci_slot {
67 struct list_head list; /* node in the list of slots */ 67 struct list_head list; /* node in the list of slots */
68}; 68};
69 69
70static int acpi_pci_slot_add(acpi_handle handle); 70static int acpi_pci_slot_add(struct acpi_pci_root *root);
71static void acpi_pci_slot_remove(acpi_handle handle); 71static void acpi_pci_slot_remove(struct acpi_pci_root *root);
72 72
73static LIST_HEAD(slot_list); 73static LIST_HEAD(slot_list);
74static DEFINE_MUTEX(slot_list_lock); 74static DEFINE_MUTEX(slot_list_lock);
@@ -233,45 +233,20 @@ out:
233 233
234/* 234/*
235 * walk_root_bridge - generic root bridge walker 235 * walk_root_bridge - generic root bridge walker
236 * @handle: points to an acpi_pci_root 236 * @root: poiner of an acpi_pci_root
237 * @user_function: user callback for slot objects 237 * @user_function: user callback for slot objects
238 * 238 *
239 * Call user_function for all objects underneath this root bridge. 239 * Call user_function for all objects underneath this root bridge.
240 * Walk p2p bridges underneath us and call user_function on those too. 240 * Walk p2p bridges underneath us and call user_function on those too.
241 */ 241 */
242static int 242static int
243walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function) 243walk_root_bridge(struct acpi_pci_root *root, acpi_walk_callback user_function)
244{ 244{
245 int seg, bus;
246 unsigned long long tmp;
247 acpi_status status; 245 acpi_status status;
248 acpi_handle dummy_handle; 246 acpi_handle handle = root->device->handle;
249 struct pci_bus *pci_bus; 247 struct pci_bus *pci_bus = root->bus;
250 struct callback_args context; 248 struct callback_args context;
251 249
252 /* If the bridge doesn't have _STA, we assume it is always there */
253 status = acpi_get_handle(handle, "_STA", &dummy_handle);
254 if (ACPI_SUCCESS(status)) {
255 status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp);
256 if (ACPI_FAILURE(status)) {
257 info("%s: _STA evaluation failure\n", __func__);
258 return 0;
259 }
260 if ((tmp & ACPI_STA_DEVICE_FUNCTIONING) == 0)
261 /* don't register this object */
262 return 0;
263 }
264
265 status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp);
266 seg = ACPI_SUCCESS(status) ? tmp : 0;
267
268 status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp);
269 bus = ACPI_SUCCESS(status) ? tmp : 0;
270
271 pci_bus = pci_find_bus(seg, bus);
272 if (!pci_bus)
273 return 0;
274
275 context.pci_bus = pci_bus; 250 context.pci_bus = pci_bus;
276 context.user_function = user_function; 251 context.user_function = user_function;
277 context.root_handle = handle; 252 context.root_handle = handle;
@@ -295,11 +270,11 @@ walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function)
295 * @handle: points to an acpi_pci_root 270 * @handle: points to an acpi_pci_root
296 */ 271 */
297static int 272static int
298acpi_pci_slot_add(acpi_handle handle) 273acpi_pci_slot_add(struct acpi_pci_root *root)
299{ 274{
300 acpi_status status; 275 acpi_status status;
301 276
302 status = walk_root_bridge(handle, register_slot); 277 status = walk_root_bridge(root, register_slot);
303 if (ACPI_FAILURE(status)) 278 if (ACPI_FAILURE(status))
304 err("%s: register_slot failure - %d\n", __func__, status); 279 err("%s: register_slot failure - %d\n", __func__, status);
305 280
@@ -311,10 +286,11 @@ acpi_pci_slot_add(acpi_handle handle)
311 * @handle: points to an acpi_pci_root 286 * @handle: points to an acpi_pci_root
312 */ 287 */
313static void 288static void
314acpi_pci_slot_remove(acpi_handle handle) 289acpi_pci_slot_remove(struct acpi_pci_root *root)
315{ 290{
316 struct acpi_pci_slot *slot, *tmp; 291 struct acpi_pci_slot *slot, *tmp;
317 struct pci_bus *pbus; 292 struct pci_bus *pbus;
293 acpi_handle handle = root->device->handle;
318 294
319 mutex_lock(&slot_list_lock); 295 mutex_lock(&slot_list_lock);
320 list_for_each_entry_safe(slot, tmp, &slot_list, list) { 296 list_for_each_entry_safe(slot, tmp, &slot_list, list) {