aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c69
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c107
-rw-r--r--drivers/pci/hotplug/pciehp_acpi.c55
-rw-r--r--include/linux/pci-acpi.h9
-rw-r--r--include/linux/pci_hotplug.h2
5 files changed, 100 insertions, 142 deletions
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index e17ef54f0efc..c62ab8d240aa 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -501,5 +501,74 @@ int acpi_root_bridge(acpi_handle handle)
501} 501}
502EXPORT_SYMBOL_GPL(acpi_root_bridge); 502EXPORT_SYMBOL_GPL(acpi_root_bridge);
503 503
504
505static int is_ejectable(acpi_handle handle)
506{
507 acpi_status status;
508 acpi_handle tmp;
509 unsigned long long removable;
510 status = acpi_get_handle(handle, "_ADR", &tmp);
511 if (ACPI_FAILURE(status))
512 return 0;
513 status = acpi_get_handle(handle, "_EJ0", &tmp);
514 if (ACPI_SUCCESS(status))
515 return 1;
516 status = acpi_evaluate_integer(handle, "_RMV", NULL, &removable);
517 if (ACPI_SUCCESS(status) && removable)
518 return 1;
519 return 0;
520}
521
522/**
523 * acpi_pcihp_check_ejectable - check if handle is ejectable ACPI PCI slot
524 * @pbus: the PCI bus of the PCI slot corresponding to 'handle'
525 * @handle: ACPI handle to check
526 *
527 * Return 1 if handle is ejectable PCI slot, 0 otherwise.
528 */
529int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle)
530{
531 acpi_handle bridge_handle, parent_handle;
532
533 if (!(bridge_handle = acpi_pci_get_bridge_handle(pbus)))
534 return 0;
535 if ((ACPI_FAILURE(acpi_get_parent(handle, &parent_handle))))
536 return 0;
537 if (bridge_handle != parent_handle)
538 return 0;
539 return is_ejectable(handle);
540}
541EXPORT_SYMBOL_GPL(acpi_pci_check_ejectable);
542
543static acpi_status
544check_hotplug(acpi_handle handle, u32 lvl, void *context, void **rv)
545{
546 int *found = (int *)context;
547 if (is_ejectable(handle)) {
548 *found = 1;
549 return AE_CTRL_TERMINATE;
550 }
551 return AE_OK;
552}
553
554/**
555 * acpi_pci_detect_ejectable - check if the PCI bus has ejectable slots
556 * @pbus - PCI bus to scan
557 *
558 * Returns 1 if the PCI bus has ACPI based ejectable slots, 0 otherwise.
559 */
560int acpi_pci_detect_ejectable(struct pci_bus *pbus)
561{
562 acpi_handle handle;
563 int found = 0;
564
565 if (!(handle = acpi_pci_get_bridge_handle(pbus)))
566 return 0;
567 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
568 check_hotplug, (void *)&found, NULL);
569 return found;
570}
571EXPORT_SYMBOL_GPL(acpi_pci_detect_ejectable);
572
504module_param(debug_acpi, bool, 0644); 573module_param(debug_acpi, bool, 0644);
505MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not"); 574MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not");
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 7a5760426897..f09b1010d477 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -46,6 +46,7 @@
46#include <linux/kernel.h> 46#include <linux/kernel.h>
47#include <linux/pci.h> 47#include <linux/pci.h>
48#include <linux/pci_hotplug.h> 48#include <linux/pci_hotplug.h>
49#include <linux/pci-acpi.h>
49#include <linux/mutex.h> 50#include <linux/mutex.h>
50 51
51#include "../pci.h" 52#include "../pci.h"
@@ -62,68 +63,6 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus);
62static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus); 63static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus);
63static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); 64static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context);
64 65
65
66/*
67 * initialization & terminatation routines
68 */
69
70/**
71 * is_ejectable - determine if a slot is ejectable
72 * @handle: handle to acpi namespace
73 *
74 * Ejectable slot should satisfy at least these conditions:
75 *
76 * 1. has _ADR method
77 * 2. has _EJ0 method or _RMV method
78 *
79 * optionally
80 *
81 * 1. has _STA method
82 * 2. has _PS0 method
83 * 3. has _PS3 method
84 * 4. ..
85 */
86static int is_ejectable(acpi_handle handle)
87{
88 acpi_status status;
89 acpi_handle tmp;
90 unsigned long long removable;
91
92 status = acpi_get_handle(handle, "_ADR", &tmp);
93 if (ACPI_FAILURE(status))
94 return 0;
95
96 status = acpi_get_handle(handle, "_EJ0", &tmp);
97 if (ACPI_SUCCESS(status))
98 return 1;
99
100 status = acpi_get_handle(handle, "_RMV", &tmp);
101 if (ACPI_SUCCESS(status)) {
102 status = acpi_evaluate_integer(handle, "_RMV", NULL,
103 &removable);
104 if (ACPI_SUCCESS(status) && removable)
105 return 1;
106 }
107
108 return 0;
109}
110
111
112/* callback routine to check for the existence of ejectable slots */
113static acpi_status
114is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
115{
116 int *count = (int *)context;
117
118 if (is_ejectable(handle)) {
119 (*count)++;
120 /* only one ejectable slot is enough */
121 return AE_CTRL_TERMINATE;
122 } else {
123 return AE_OK;
124 }
125}
126
127/* callback routine to check for the existence of a pci dock device */ 66/* callback routine to check for the existence of a pci dock device */
128static acpi_status 67static acpi_status
129is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) 68is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
@@ -138,9 +77,6 @@ is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
138 } 77 }
139} 78}
140 79
141
142
143
144/* 80/*
145 * the _DCK method can do funny things... and sometimes not 81 * the _DCK method can do funny things... and sometimes not
146 * hah-hah funny. 82 * hah-hah funny.
@@ -191,8 +127,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
191 acpi_status status = AE_OK; 127 acpi_status status = AE_OK;
192 unsigned long long adr, sun; 128 unsigned long long adr, sun;
193 int device, function, retval; 129 int device, function, retval;
130 struct pci_bus *pbus = bridge->pci_bus;
194 131
195 if (!is_ejectable(handle) && !is_dock_device(handle)) 132 if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))
196 return AE_OK; 133 return AE_OK;
197 134
198 acpi_evaluate_integer(handle, "_ADR", NULL, &adr); 135 acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
@@ -258,8 +195,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
258 bridge->nr_slots++; 195 bridge->nr_slots++;
259 196
260 dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", 197 dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n",
261 slot->sun, pci_domain_nr(bridge->pci_bus), 198 slot->sun, pci_domain_nr(pbus), pbus->number, device);
262 bridge->pci_bus->number, slot->device);
263 retval = acpiphp_register_hotplug_slot(slot); 199 retval = acpiphp_register_hotplug_slot(slot);
264 if (retval) { 200 if (retval) {
265 if (retval == -EBUSY) 201 if (retval == -EBUSY)
@@ -276,8 +212,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
276 list_add_tail(&newfunc->sibling, &slot->funcs); 212 list_add_tail(&newfunc->sibling, &slot->funcs);
277 213
278 /* associate corresponding pci_dev */ 214 /* associate corresponding pci_dev */
279 newfunc->pci_dev = pci_get_slot(bridge->pci_bus, 215 newfunc->pci_dev = pci_get_slot(pbus, PCI_DEVFN(device, function));
280 PCI_DEVFN(device, function));
281 if (newfunc->pci_dev) { 216 if (newfunc->pci_dev) {
282 slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); 217 slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
283 } 218 }
@@ -326,27 +261,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
326 261
327 262
328/* see if it's worth looking at this bridge */ 263/* see if it's worth looking at this bridge */
329static int detect_ejectable_slots(acpi_handle *bridge_handle) 264static int detect_ejectable_slots(struct pci_bus *pbus)
330{ 265{
331 acpi_status status; 266 int found = acpi_pci_detect_ejectable(pbus);
332 int count; 267 if (!found) {
333 268 acpi_handle bridge_handle = acpi_pci_get_bridge_handle(pbus);
334 count = 0; 269 acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1,
335 270 is_pci_dock_device, (void *)&found, NULL);
336 /* only check slots defined directly below bridge object */ 271 }
337 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1, 272 return found;
338 is_ejectable_slot, (void *)&count, NULL);
339
340 /*
341 * we also need to add this bridge if there is a dock bridge or
342 * other pci device on a dock station (removable)
343 */
344 if (!count)
345 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle,
346 (u32)1, is_pci_dock_device, (void *)&count,
347 NULL);
348
349 return count;
350} 273}
351 274
352 275
@@ -556,7 +479,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
556 goto out; 479 goto out;
557 480
558 /* check if this bridge has ejectable slots */ 481 /* check if this bridge has ejectable slots */
559 if ((detect_ejectable_slots(handle) > 0)) { 482 if ((detect_ejectable_slots(dev->subordinate) > 0)) {
560 dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); 483 dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
561 add_p2p_bridge(handle, dev); 484 add_p2p_bridge(handle, dev);
562 } 485 }
@@ -617,7 +540,7 @@ static int add_bridge(acpi_handle handle)
617 } 540 }
618 541
619 /* check if this bridge has ejectable slots */ 542 /* check if this bridge has ejectable slots */
620 if (detect_ejectable_slots(handle) > 0) { 543 if (detect_ejectable_slots(pci_bus) > 0) {
621 dbg("found PCI host-bus bridge with hot-pluggable slots\n"); 544 dbg("found PCI host-bus bridge with hot-pluggable slots\n");
622 add_host_bridge(handle, pci_bus); 545 add_host_bridge(handle, pci_bus);
623 } 546 }
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c
index 88a5c57f2e5b..438d795f9fe3 100644
--- a/drivers/pci/hotplug/pciehp_acpi.c
+++ b/drivers/pci/hotplug/pciehp_acpi.c
@@ -24,6 +24,8 @@
24 */ 24 */
25 25
26#include <linux/acpi.h> 26#include <linux/acpi.h>
27#include <linux/pci.h>
28#include <linux/pci_hotplug.h>
27#include "pciehp.h" 29#include "pciehp.h"
28 30
29#define PCIEHP_DETECT_PCIE (0) 31#define PCIEHP_DETECT_PCIE (0)
@@ -41,59 +43,11 @@ MODULE_PARM_DESC(pciehp_detect_mode,
41 " auto(default) - Auto select mode. Use acpi option if duplicate\n" 43 " auto(default) - Auto select mode. Use acpi option if duplicate\n"
42 " slot ids are found. Otherwise, use pcie option\n"); 44 " slot ids are found. Otherwise, use pcie option\n");
43 45
44static int is_ejectable(acpi_handle handle)
45{
46 acpi_status status;
47 acpi_handle tmp;
48 unsigned long long removable;
49 status = acpi_get_handle(handle, "_ADR", &tmp);
50 if (ACPI_FAILURE(status))
51 return 0;
52 status = acpi_get_handle(handle, "_EJ0", &tmp);
53 if (ACPI_SUCCESS(status))
54 return 1;
55 status = acpi_evaluate_integer(handle, "_RMV", NULL, &removable);
56 if (ACPI_SUCCESS(status) && removable)
57 return 1;
58 return 0;
59}
60
61static acpi_status
62check_hotplug(acpi_handle handle, u32 lvl, void *context, void **rv)
63{
64 int *found = (int *)context;
65 if (is_ejectable(handle)) {
66 *found = 1;
67 return AE_CTRL_TERMINATE;
68 }
69 return AE_OK;
70}
71
72static int pciehp_detect_acpi_slot(struct pci_bus *pbus)
73{
74 acpi_handle handle;
75 struct pci_dev *pdev = pbus->self;
76 int found = 0;
77
78 if (!pdev){
79 int seg = pci_domain_nr(pbus), busnr = pbus->number;
80 handle = acpi_get_pci_rootbridge_handle(seg, busnr);
81 } else
82 handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
83
84 if (!handle)
85 return 0;
86
87 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
88 check_hotplug, (void *)&found, NULL);
89 return found;
90}
91
92int pciehp_acpi_slot_detection_check(struct pci_dev *dev) 46int pciehp_acpi_slot_detection_check(struct pci_dev *dev)
93{ 47{
94 if (slot_detection_mode != PCIEHP_DETECT_ACPI) 48 if (slot_detection_mode != PCIEHP_DETECT_ACPI)
95 return 0; 49 return 0;
96 if (pciehp_detect_acpi_slot(dev->subordinate)) 50 if (acpi_pci_detect_ejectable(dev->subordinate))
97 return 0; 51 return 0;
98 return -ENODEV; 52 return -ENODEV;
99} 53}
@@ -135,6 +89,7 @@ static int __init dummy_probe(struct pcie_device *dev,
135 u32 slot_cap; 89 u32 slot_cap;
136 struct slot *slot, *tmp; 90 struct slot *slot, *tmp;
137 struct pci_dev *pdev = dev->port; 91 struct pci_dev *pdev = dev->port;
92 struct pci_bus *pbus = pdev->subordinate;
138 if (!(slot = kzalloc(sizeof(*slot), GFP_KERNEL))) 93 if (!(slot = kzalloc(sizeof(*slot), GFP_KERNEL)))
139 return -ENOMEM; 94 return -ENOMEM;
140 /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */ 95 /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */
@@ -149,7 +104,7 @@ static int __init dummy_probe(struct pcie_device *dev,
149 dup_slot_id++; 104 dup_slot_id++;
150 } 105 }
151 list_add_tail(&slot->slot_list, &dummy_slots); 106 list_add_tail(&slot->slot_list, &dummy_slots);
152 if (!acpi_slot_detected && pciehp_detect_acpi_slot(pdev->subordinate)) 107 if (!acpi_slot_detected && acpi_pci_detect_ejectable(pbus))
153 acpi_slot_detected = 1; 108 acpi_slot_detected = 1;
154 return -ENODEV; /* dummy driver always returns error */ 109 return -ENODEV; /* dummy driver always returns error */
155} 110}
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 871e096e0fbc..042c166f65d5 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -60,6 +60,15 @@ static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
60 return acpi_get_pci_rootbridge_handle(pci_domain_nr(pdev->bus), 60 return acpi_get_pci_rootbridge_handle(pci_domain_nr(pdev->bus),
61 pdev->bus->number); 61 pdev->bus->number);
62} 62}
63
64static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus)
65{
66 int seg = pci_domain_nr(pbus), busnr = pbus->number;
67 struct pci_dev *bridge = pbus->self;
68 if (bridge)
69 return DEVICE_ACPI_HANDLE(&(bridge->dev));
70 return acpi_get_pci_rootbridge_handle(seg, busnr);
71}
63#else 72#else
64#if !defined(AE_ERROR) 73#if !defined(AE_ERROR)
65typedef u32 acpi_status; 74typedef u32 acpi_status;
diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
index a00bd1a0f156..f7cc204fab07 100644
--- a/include/linux/pci_hotplug.h
+++ b/include/linux/pci_hotplug.h
@@ -228,6 +228,8 @@ extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
228 struct hotplug_params *hpp); 228 struct hotplug_params *hpp);
229int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags); 229int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags);
230int acpi_root_bridge(acpi_handle handle); 230int acpi_root_bridge(acpi_handle handle);
231int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle);
232int acpi_pci_detect_ejectable(struct pci_bus *pbus);
231#endif 233#endif
232#endif 234#endif
233 235