aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2012-09-24 18:36:10 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-09-24 18:36:10 -0400
commit18d63c35a265465b7137c4ea9c6b135aada13c3c (patch)
tree1bff6e43ec609a86596d4704f3d50cf0adcfff74
parent168ae6a08aa6e0cf8b0166dedeb675a20af1fbb7 (diff)
parentcd4faf9c34b27cbb6bcc70a4f1d1759f2e6fa7fd (diff)
Merge branch 'pci/taku-acpi-pci-host-bridge-v3' into next
-rw-r--r--drivers/acpi/pci_root.c101
-rw-r--r--drivers/acpi/pci_slot.c44
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c12
-rw-r--r--include/linux/acpi.h6
-rw-r--r--include/linux/pci-acpi.h17
5 files changed, 89 insertions, 91 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 72a2c98bc42..bce469c0b48 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 e50e31a518a..d22585f21ae 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) {
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 7be4ca5e1f4..466233b481b 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -382,10 +382,10 @@ static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge)
382 382
383 383
384/* allocate and initialize host bridge data structure */ 384/* allocate and initialize host bridge data structure */
385static void add_host_bridge(acpi_handle *handle) 385static void add_host_bridge(struct acpi_pci_root *root)
386{ 386{
387 struct acpiphp_bridge *bridge; 387 struct acpiphp_bridge *bridge;
388 struct acpi_pci_root *root = acpi_pci_find_root(handle); 388 acpi_handle handle = root->device->handle;
389 389
390 bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); 390 bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
391 if (bridge == NULL) 391 if (bridge == NULL)
@@ -468,11 +468,12 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
468 468
469 469
470/* find hot-pluggable slots, and then find P2P bridge */ 470/* find hot-pluggable slots, and then find P2P bridge */
471static int add_bridge(acpi_handle handle) 471static int add_bridge(struct acpi_pci_root *root)
472{ 472{
473 acpi_status status; 473 acpi_status status;
474 unsigned long long tmp; 474 unsigned long long tmp;
475 acpi_handle dummy_handle; 475 acpi_handle dummy_handle;
476 acpi_handle handle = root->device->handle;
476 477
477 /* if the bridge doesn't have _STA, we assume it is always there */ 478 /* if the bridge doesn't have _STA, we assume it is always there */
478 status = acpi_get_handle(handle, "_STA", &dummy_handle); 479 status = acpi_get_handle(handle, "_STA", &dummy_handle);
@@ -490,7 +491,7 @@ static int add_bridge(acpi_handle handle)
490 /* check if this bridge has ejectable slots */ 491 /* check if this bridge has ejectable slots */
491 if (detect_ejectable_slots(handle) > 0) { 492 if (detect_ejectable_slots(handle) > 0) {
492 dbg("found PCI host-bus bridge with hot-pluggable slots\n"); 493 dbg("found PCI host-bus bridge with hot-pluggable slots\n");
493 add_host_bridge(handle); 494 add_host_bridge(root);
494 } 495 }
495 496
496 /* search P2P bridges under this host bridge */ 497 /* search P2P bridges under this host bridge */
@@ -588,9 +589,10 @@ cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
588 return AE_OK; 589 return AE_OK;
589} 590}
590 591
591static void remove_bridge(acpi_handle handle) 592static void remove_bridge(struct acpi_pci_root *root)
592{ 593{
593 struct acpiphp_bridge *bridge; 594 struct acpiphp_bridge *bridge;
595 acpi_handle handle = root->device->handle;
594 596
595 /* cleanup p2p bridges under this host bridge 597 /* cleanup p2p bridges under this host bridge
596 in a depth-first manner */ 598 in a depth-first manner */
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 4f2a7622450..90be9898110 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -138,9 +138,9 @@ void acpi_penalize_isa_irq(int irq, int active);
138void acpi_pci_irq_disable (struct pci_dev *dev); 138void acpi_pci_irq_disable (struct pci_dev *dev);
139 139
140struct acpi_pci_driver { 140struct acpi_pci_driver {
141 struct acpi_pci_driver *next; 141 struct list_head node;
142 int (*add)(acpi_handle handle); 142 int (*add)(struct acpi_pci_root *root);
143 void (*remove)(acpi_handle handle); 143 void (*remove)(struct acpi_pci_root *root);
144}; 144};
145 145
146int acpi_pci_register_driver(struct acpi_pci_driver *driver); 146int acpi_pci_register_driver(struct acpi_pci_driver *driver);
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 248fba2af98..9a22b5efb38 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -22,19 +22,24 @@ extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle);
22static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev) 22static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
23{ 23{
24 struct pci_bus *pbus = pdev->bus; 24 struct pci_bus *pbus = pdev->bus;
25
25 /* Find a PCI root bus */ 26 /* Find a PCI root bus */
26 while (!pci_is_root_bus(pbus)) 27 while (!pci_is_root_bus(pbus))
27 pbus = pbus->parent; 28 pbus = pbus->parent;
28 return acpi_get_pci_rootbridge_handle(pci_domain_nr(pbus), 29
29 pbus->number); 30 return DEVICE_ACPI_HANDLE(pbus->bridge);
30} 31}
31 32
32static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus) 33static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus)
33{ 34{
34 if (!pci_is_root_bus(pbus)) 35 struct device *dev;
35 return DEVICE_ACPI_HANDLE(&(pbus->self->dev)); 36
36 return acpi_get_pci_rootbridge_handle(pci_domain_nr(pbus), 37 if (pci_is_root_bus(pbus))
37 pbus->number); 38 dev = pbus->bridge;
39 else
40 dev = &pbus->self->dev;
41
42 return DEVICE_ACPI_HANDLE(dev);
38} 43}
39#endif 44#endif
40 45