aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/acpiphp_glue.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c107
1 files changed, 15 insertions, 92 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 7a576042689..f09b1010d47 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 }