diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/pci_root.c | 101 | ||||
-rw-r--r-- | drivers/acpi/pci_slot.c | 44 |
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 */ | ||
75 | static DEFINE_MUTEX(acpi_pci_root_lock); | ||
74 | static LIST_HEAD(acpi_pci_roots); | 76 | static LIST_HEAD(acpi_pci_roots); |
77 | static LIST_HEAD(acpi_pci_drivers); | ||
75 | 78 | ||
76 | static struct acpi_pci_driver *sub_driver; | ||
77 | static DEFINE_MUTEX(osc_lock); | 79 | static DEFINE_MUTEX(osc_lock); |
78 | 80 | ||
79 | int acpi_pci_register_driver(struct acpi_pci_driver *driver) | 81 | int 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 | |||
100 | EXPORT_SYMBOL(acpi_pci_register_driver); | 97 | EXPORT_SYMBOL(acpi_pci_register_driver); |
101 | 98 | ||
102 | void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) | 99 | void 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 | |||
122 | EXPORT_SYMBOL(acpi_pci_unregister_driver); | 110 | EXPORT_SYMBOL(acpi_pci_unregister_driver); |
123 | 111 | ||
124 | 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) |
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 | ||
135 | EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); | 128 | EXPORT_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) | |||
277 | struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) | 270 | struct 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 | } |
287 | EXPORT_SYMBOL_GPL(acpi_pci_find_root); | 283 | EXPORT_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 | ||
633 | out_del_root: | ||
634 | mutex_lock(&acpi_pci_root_lock); | ||
635 | list_del(&root->node); | ||
636 | mutex_unlock(&acpi_pci_root_lock); | ||
636 | end: | 637 | end: |
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: | |||
643 | static int acpi_pci_root_start(struct acpi_device *device) | 642 | static 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 | ||
651 | static int acpi_pci_root_remove(struct acpi_device *device, int type) | 658 | static 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 | ||
70 | static int acpi_pci_slot_add(acpi_handle handle); | 70 | static int acpi_pci_slot_add(struct acpi_pci_root *root); |
71 | static void acpi_pci_slot_remove(acpi_handle handle); | 71 | static void acpi_pci_slot_remove(struct acpi_pci_root *root); |
72 | 72 | ||
73 | static LIST_HEAD(slot_list); | 73 | static LIST_HEAD(slot_list); |
74 | static DEFINE_MUTEX(slot_list_lock); | 74 | static 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 | */ |
242 | static int | 242 | static int |
243 | walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function) | 243 | walk_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 | */ |
297 | static int | 272 | static int |
298 | acpi_pci_slot_add(acpi_handle handle) | 273 | acpi_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 | */ |
313 | static void | 288 | static void |
314 | acpi_pci_slot_remove(acpi_handle handle) | 289 | acpi_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) { |