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.c117
1 files changed, 21 insertions, 96 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 3affc6472e65..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,61 +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
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
91 status = acpi_get_handle(handle, "_ADR", &tmp);
92 if (ACPI_FAILURE(status)) {
93 return 0;
94 }
95
96 status = acpi_get_handle(handle, "_EJ0", &tmp);
97 if (ACPI_FAILURE(status)) {
98 return 0;
99 }
100
101 return 1;
102}
103
104
105/* callback routine to check for the existence of ejectable slots */
106static acpi_status
107is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
108{
109 int *count = (int *)context;
110
111 if (is_ejectable(handle)) {
112 (*count)++;
113 /* only one ejectable slot is enough */
114 return AE_CTRL_TERMINATE;
115 } else {
116 return AE_OK;
117 }
118}
119
120/* 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 */
121static acpi_status 67static acpi_status
122is_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)
@@ -131,9 +77,6 @@ is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
131 } 77 }
132} 78}
133 79
134
135
136
137/* 80/*
138 * the _DCK method can do funny things... and sometimes not 81 * the _DCK method can do funny things... and sometimes not
139 * hah-hah funny. 82 * hah-hah funny.
@@ -160,9 +103,9 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
160 103
161 if (((buses >> 8) & 0xff) != bus->secondary) { 104 if (((buses >> 8) & 0xff) != bus->secondary) {
162 buses = (buses & 0xff000000) 105 buses = (buses & 0xff000000)
163 | ((unsigned int)(bus->primary) << 0) 106 | ((unsigned int)(bus->primary) << 0)
164 | ((unsigned int)(bus->secondary) << 8) 107 | ((unsigned int)(bus->secondary) << 8)
165 | ((unsigned int)(bus->subordinate) << 16); 108 | ((unsigned int)(bus->subordinate) << 16);
166 pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses); 109 pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);
167 } 110 }
168 return NOTIFY_OK; 111 return NOTIFY_OK;
@@ -184,17 +127,12 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
184 acpi_status status = AE_OK; 127 acpi_status status = AE_OK;
185 unsigned long long adr, sun; 128 unsigned long long adr, sun;
186 int device, function, retval; 129 int device, function, retval;
130 struct pci_bus *pbus = bridge->pci_bus;
187 131
188 status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); 132 if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))
189
190 if (ACPI_FAILURE(status))
191 return AE_OK;
192
193 status = acpi_get_handle(handle, "_EJ0", &tmp);
194
195 if (ACPI_FAILURE(status) && !(is_dock_device(handle)))
196 return AE_OK; 133 return AE_OK;
197 134
135 acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
198 device = (adr >> 16) & 0xffff; 136 device = (adr >> 16) & 0xffff;
199 function = adr & 0xffff; 137 function = adr & 0xffff;
200 138
@@ -205,7 +143,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
205 INIT_LIST_HEAD(&newfunc->sibling); 143 INIT_LIST_HEAD(&newfunc->sibling);
206 newfunc->handle = handle; 144 newfunc->handle = handle;
207 newfunc->function = function; 145 newfunc->function = function;
208 if (ACPI_SUCCESS(status)) 146
147 if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
209 newfunc->flags = FUNC_HAS_EJ0; 148 newfunc->flags = FUNC_HAS_EJ0;
210 149
211 if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp))) 150 if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp)))
@@ -256,8 +195,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
256 bridge->nr_slots++; 195 bridge->nr_slots++;
257 196
258 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",
259 slot->sun, pci_domain_nr(bridge->pci_bus), 198 slot->sun, pci_domain_nr(pbus), pbus->number, device);
260 bridge->pci_bus->number, slot->device);
261 retval = acpiphp_register_hotplug_slot(slot); 199 retval = acpiphp_register_hotplug_slot(slot);
262 if (retval) { 200 if (retval) {
263 if (retval == -EBUSY) 201 if (retval == -EBUSY)
@@ -274,8 +212,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
274 list_add_tail(&newfunc->sibling, &slot->funcs); 212 list_add_tail(&newfunc->sibling, &slot->funcs);
275 213
276 /* associate corresponding pci_dev */ 214 /* associate corresponding pci_dev */
277 newfunc->pci_dev = pci_get_slot(bridge->pci_bus, 215 newfunc->pci_dev = pci_get_slot(pbus, PCI_DEVFN(device, function));
278 PCI_DEVFN(device, function));
279 if (newfunc->pci_dev) { 216 if (newfunc->pci_dev) {
280 slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); 217 slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
281 } 218 }
@@ -324,27 +261,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
324 261
325 262
326/* see if it's worth looking at this bridge */ 263/* see if it's worth looking at this bridge */
327static int detect_ejectable_slots(acpi_handle *bridge_handle) 264static int detect_ejectable_slots(struct pci_bus *pbus)
328{ 265{
329 acpi_status status; 266 int found = acpi_pci_detect_ejectable(pbus);
330 int count; 267 if (!found) {
331 268 acpi_handle bridge_handle = acpi_pci_get_bridge_handle(pbus);
332 count = 0; 269 acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1,
333 270 is_pci_dock_device, (void *)&found, NULL);
334 /* only check slots defined directly below bridge object */ 271 }
335 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1, 272 return found;
336 is_ejectable_slot, (void *)&count, NULL);
337
338 /*
339 * we also need to add this bridge if there is a dock bridge or
340 * other pci device on a dock station (removable)
341 */
342 if (!count)
343 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle,
344 (u32)1, is_pci_dock_device, (void *)&count,
345 NULL);
346
347 return count;
348} 273}
349 274
350 275
@@ -554,7 +479,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
554 goto out; 479 goto out;
555 480
556 /* check if this bridge has ejectable slots */ 481 /* check if this bridge has ejectable slots */
557 if ((detect_ejectable_slots(handle) > 0)) { 482 if ((detect_ejectable_slots(dev->subordinate) > 0)) {
558 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));
559 add_p2p_bridge(handle, dev); 484 add_p2p_bridge(handle, dev);
560 } 485 }
@@ -615,7 +540,7 @@ static int add_bridge(acpi_handle handle)
615 } 540 }
616 541
617 /* check if this bridge has ejectable slots */ 542 /* check if this bridge has ejectable slots */
618 if (detect_ejectable_slots(handle) > 0) { 543 if (detect_ejectable_slots(pci_bus) > 0) {
619 dbg("found PCI host-bus bridge with hot-pluggable slots\n"); 544 dbg("found PCI host-bus bridge with hot-pluggable slots\n");
620 add_host_bridge(handle, pci_bus); 545 add_host_bridge(handle, pci_bus);
621 } 546 }