aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/acpiphp_glue.c
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2008-12-16 22:09:12 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-01-07 14:13:11 -0500
commite8c331e963c58b83db24b7d0e39e8c07f687dbc6 (patch)
treeda9e7df2441da952dc11bd732b0171d3170fa8bf /drivers/pci/hotplug/acpiphp_glue.c
parente046cbd6c05ee859244245d7beeac395cd0057b3 (diff)
PCI hotplug: introduce functions for ACPI slot detection
Some ACPI related PCI hotplug code can be shared among PCI hotplug drivers. This patch introduces the following functions in drivers/pci/hotplug/acpi_pcihp.c to share the code, and changes acpiphp and pciehp to use them. - int acpi_pci_detect_ejectable(struct pci_bus *pbus) This checks if the specified PCI bus has ejectable slots. - int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle) This checks if the specified handle is ejectable ACPI PCI slot. The 'pbus' parameter is needed to check if 'handle' is PCI related ACPI object. This patch also introduces the following inline function in include/linux/pci-acpi.h, which is useful to get ACPI handle of the PCI bridge from struct pci_bus of the bridge's secondary bus. - static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus) This returns ACPI handle of the PCI bridge which generates PCI bus specified by 'pbus'. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
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 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 }