blob: faf7eed5d9630f2a829b6eb9011f96b2db6eeed0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ACPI PCI HotPlug glue functions to ACPI CA subsystem
3 *
4 * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)
5 * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
6 * Copyright (C) 2002,2003 NEC Corporation
Rajesh Shah42f49a62005-04-28 00:25:53 -07007 * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com)
8 * Copyright (C) 2003-2005 Hewlett Packard
Rajesh Shah8e7561c2005-04-28 00:25:56 -07009 * Copyright (C) 2005 Rajesh Shah (rajesh.shah@intel.com)
10 * Copyright (C) 2005 Intel Corporation
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 *
12 * All rights reserved.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or (at
17 * your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
22 * NON INFRINGEMENT. See the GNU General Public License for more
23 * details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 *
29 * Send feedback to <t-kochi@bq.jp.nec.com>
30 *
31 */
32
Rajesh Shah42f49a62005-04-28 00:25:53 -070033/*
34 * Lifetime rules for pci_dev:
35 * - The one in acpiphp_func has its refcount elevated by pci_get_slot()
36 * when the driver is loaded or when an insertion event occurs. It loses
37 * a refcount when its ejected or the driver unloads.
38 * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot()
39 * when the bridge is scanned and it loses a refcount when the bridge
40 * is removed.
41 */
42
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/init.h>
44#include <linux/module.h>
45
46#include <linux/kernel.h>
47#include <linux/pci.h>
48#include <linux/smp_lock.h>
Ingo Molnar6aa4cdd2006-01-13 16:02:15 +010049#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51#include "../pci.h"
52#include "pci_hotplug.h"
53#include "acpiphp.h"
54
55static LIST_HEAD(bridge_list);
56
57#define MY_NAME "acpiphp_glue"
58
59static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
Kristen Accardi8e5dce32005-10-18 17:21:40 -070060static void acpiphp_sanitize_bus(struct pci_bus *bus);
61static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus);
62
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
64/*
65 * initialization & terminatation routines
66 */
67
68/**
69 * is_ejectable - determine if a slot is ejectable
70 * @handle: handle to acpi namespace
71 *
72 * Ejectable slot should satisfy at least these conditions:
73 *
74 * 1. has _ADR method
75 * 2. has _EJ0 method
76 *
77 * optionally
78 *
79 * 1. has _STA method
80 * 2. has _PS0 method
81 * 3. has _PS3 method
82 * 4. ..
83 *
84 */
85static int is_ejectable(acpi_handle handle)
86{
87 acpi_status status;
88 acpi_handle tmp;
89
90 status = acpi_get_handle(handle, "_ADR", &tmp);
91 if (ACPI_FAILURE(status)) {
92 return 0;
93 }
94
95 status = acpi_get_handle(handle, "_EJ0", &tmp);
96 if (ACPI_FAILURE(status)) {
97 return 0;
98 }
99
100 return 1;
101}
102
103
104/* callback routine to check the existence of ejectable slots */
105static acpi_status
106is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
107{
108 int *count = (int *)context;
109
110 if (is_ejectable(handle)) {
111 (*count)++;
112 /* only one ejectable slot is enough */
113 return AE_CTRL_TERMINATE;
114 } else {
115 return AE_OK;
116 }
117}
118
Kristen Accardi4e8662b2006-06-28 03:08:06 -0400119/* callback routine to check for the existance of a pci dock device */
120static acpi_status
121is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
122{
123 int *count = (int *)context;
124
125 if (is_dock_device(handle)) {
126 (*count)++;
127 return AE_CTRL_TERMINATE;
128 } else {
129 return AE_OK;
130 }
131}
132
133
134
135
136/*
137 * the _DCK method can do funny things... and sometimes not
138 * hah-hah funny.
139 *
140 * TBD - figure out a way to only call fixups for
141 * systems that require them.
142 */
143static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
144 void *v)
145{
146 struct acpiphp_func *func = container_of(nb, struct acpiphp_func, nb);
147 struct pci_bus *bus = func->slot->bridge->pci_bus;
148 u32 buses;
149
150 if (!bus->self)
151 return NOTIFY_OK;
152
153 /* fixup bad _DCK function that rewrites
154 * secondary bridge on slot
155 */
156 pci_read_config_dword(bus->self,
157 PCI_PRIMARY_BUS,
158 &buses);
159
160 if (((buses >> 8) & 0xff) != bus->secondary) {
161 buses = (buses & 0xff000000)
162 | ((unsigned int)(bus->primary) << 0)
163 | ((unsigned int)(bus->secondary) << 8)
164 | ((unsigned int)(bus->subordinate) << 16);
165 pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);
166 }
167 return NOTIFY_OK;
168}
169
170
171
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
173/* callback routine to register each ACPI PCI slot object */
174static acpi_status
175register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
176{
177 struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context;
178 struct acpiphp_slot *slot;
179 struct acpiphp_func *newfunc;
180 acpi_handle tmp;
181 acpi_status status = AE_OK;
182 unsigned long adr, sun;
MUNEDA Takahiroe27da382006-02-23 17:56:08 -0800183 int device, function, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184
185 status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
186
187 if (ACPI_FAILURE(status))
188 return AE_OK;
189
190 status = acpi_get_handle(handle, "_EJ0", &tmp);
191
Kristen Accardi4e8662b2006-06-28 03:08:06 -0400192 if (ACPI_FAILURE(status) && !(is_dock_device(handle)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 return AE_OK;
194
195 device = (adr >> 16) & 0xffff;
196 function = adr & 0xffff;
197
Eric Sesterhennf5afe802006-02-28 15:34:49 +0100198 newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 if (!newfunc)
200 return AE_NO_MEMORY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
202 INIT_LIST_HEAD(&newfunc->sibling);
203 newfunc->handle = handle;
204 newfunc->function = function;
Kristen Accardi20416ea2006-02-23 17:56:03 -0800205 if (ACPI_SUCCESS(status))
206 newfunc->flags = FUNC_HAS_EJ0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207
208 if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp)))
209 newfunc->flags |= FUNC_HAS_STA;
210
211 if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS0", &tmp)))
212 newfunc->flags |= FUNC_HAS_PS0;
213
214 if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp)))
215 newfunc->flags |= FUNC_HAS_PS3;
216
Kristen Accardi4e8662b2006-06-28 03:08:06 -0400217 if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp)))
Kristen Accardi20416ea2006-02-23 17:56:03 -0800218 newfunc->flags |= FUNC_HAS_DCK;
Kristen Accardi20416ea2006-02-23 17:56:03 -0800219
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun);
221 if (ACPI_FAILURE(status))
222 sun = -1;
223
224 /* search for objects that share the same slot */
225 for (slot = bridge->slots; slot; slot = slot->next)
226 if (slot->device == device) {
227 if (slot->sun != sun)
228 warn("sibling found, but _SUN doesn't match!\n");
229 break;
230 }
231
232 if (!slot) {
Eric Sesterhennf5afe802006-02-28 15:34:49 +0100233 slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 if (!slot) {
235 kfree(newfunc);
236 return AE_NO_MEMORY;
237 }
238
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 slot->bridge = bridge;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 slot->device = device;
241 slot->sun = sun;
242 INIT_LIST_HEAD(&slot->funcs);
Ingo Molnar6aa4cdd2006-01-13 16:02:15 +0100243 mutex_init(&slot->crit_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244
245 slot->next = bridge->slots;
246 bridge->slots = slot;
247
248 bridge->nr_slots++;
249
Rajesh Shah42f49a62005-04-28 00:25:53 -0700250 dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n",
251 slot->sun, pci_domain_nr(bridge->pci_bus),
252 bridge->pci_bus->number, slot->device);
MUNEDA Takahiroe27da382006-02-23 17:56:08 -0800253 retval = acpiphp_register_hotplug_slot(slot);
254 if (retval) {
255 warn("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n", retval);
256 goto err_exit;
257 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 }
259
260 newfunc->slot = slot;
261 list_add_tail(&newfunc->sibling, &slot->funcs);
262
263 /* associate corresponding pci_dev */
Rajesh Shah42f49a62005-04-28 00:25:53 -0700264 newfunc->pci_dev = pci_get_slot(bridge->pci_bus,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 PCI_DEVFN(device, function));
266 if (newfunc->pci_dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
268 }
269
Kristen Accardi4e8662b2006-06-28 03:08:06 -0400270 if (is_dock_device(handle)) {
271 /* we don't want to call this device's _EJ0
272 * because we want the dock notify handler
273 * to call it after it calls _DCK
Kristen Accardi20416ea2006-02-23 17:56:03 -0800274 */
275 newfunc->flags &= ~FUNC_HAS_EJ0;
Kristen Accardi4e8662b2006-06-28 03:08:06 -0400276 if (register_hotplug_dock_device(handle,
277 handle_hotplug_event_func, newfunc))
278 dbg("failed to register dock device\n");
279
280 /* we need to be notified when dock events happen
281 * outside of the hotplug operation, since we may
282 * need to do fixups before we can hotplug.
283 */
284 newfunc->nb.notifier_call = post_dock_fixups;
285 if (register_dock_notifier(&newfunc->nb))
286 dbg("failed to register a dock notifier");
Kristen Accardi20416ea2006-02-23 17:56:03 -0800287 }
288
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 /* install notify handler */
Kristen Accardi20416ea2006-02-23 17:56:03 -0800290 if (!(newfunc->flags & FUNC_HAS_DCK)) {
291 status = acpi_install_notify_handler(handle,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 ACPI_SYSTEM_NOTIFY,
293 handle_hotplug_event_func,
294 newfunc);
295
Kristen Accardi20416ea2006-02-23 17:56:03 -0800296 if (ACPI_FAILURE(status))
297 err("failed to register interrupt notify handler\n");
298 } else
299 status = AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
Kristen Accardi20416ea2006-02-23 17:56:03 -0800301 return status;
MUNEDA Takahiroe27da382006-02-23 17:56:08 -0800302
303 err_exit:
304 bridge->nr_slots--;
305 bridge->slots = slot->next;
306 kfree(slot);
307 kfree(newfunc);
308
309 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310}
311
312
313/* see if it's worth looking at this bridge */
314static int detect_ejectable_slots(acpi_handle *bridge_handle)
315{
316 acpi_status status;
317 int count;
318
319 count = 0;
320
321 /* only check slots defined directly below bridge object */
322 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1,
323 is_ejectable_slot, (void *)&count, NULL);
324
Kristen Accardi4e8662b2006-06-28 03:08:06 -0400325 /*
326 * we also need to add this bridge if there is a dock bridge or
327 * other pci device on a dock station (removable)
328 */
329 if (!count)
330 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle,
331 (u32)1, is_pci_dock_device, (void *)&count,
332 NULL);
333
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 return count;
335}
336
337
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338/* decode ACPI 2.0 _HPP hot plug parameters */
339static void decode_hpp(struct acpiphp_bridge *bridge)
340{
341 acpi_status status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
Kenji Kaneshige7430e342006-05-02 10:54:50 +0900343 status = acpi_get_hp_params_from_firmware(bridge->pci_bus, &bridge->hpp);
Kenji Kaneshigee22b73502006-05-02 10:57:14 +0900344 if (ACPI_FAILURE(status) ||
345 !bridge->hpp.t0 || (bridge->hpp.t0->revision > 1)) {
Kristen Accardi783c49f2006-03-03 10:16:05 -0800346 /* use default numbers */
Kenji Kaneshigee22b73502006-05-02 10:57:14 +0900347 printk(KERN_WARNING
348 "%s: Could not get hotplug parameters. Use defaults\n",
349 __FUNCTION__);
350 bridge->hpp.t0 = &bridge->hpp.type0_data;
351 bridge->hpp.t0->revision = 0;
352 bridge->hpp.t0->cache_line_size = 0x10;
353 bridge->hpp.t0->latency_timer = 0x40;
354 bridge->hpp.t0->enable_serr = 0;
355 bridge->hpp.t0->enable_perr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357}
358
359
Kristen Accardi783c49f2006-03-03 10:16:05 -0800360
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361/* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */
362static void init_bridge_misc(struct acpiphp_bridge *bridge)
363{
364 acpi_status status;
365
366 /* decode ACPI 2.0 _HPP (hot plug parameters) */
367 decode_hpp(bridge);
368
MUNEDA Takahiroe27da382006-02-23 17:56:08 -0800369 /* must be added to the list prior to calling register_slot */
370 list_add(&bridge->list, &bridge_list);
371
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 /* register all slot objects under this bridge */
373 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
374 register_slot, bridge, NULL);
MUNEDA Takahiroe27da382006-02-23 17:56:08 -0800375 if (ACPI_FAILURE(status)) {
376 list_del(&bridge->list);
377 return;
378 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379
380 /* install notify handler */
Rajesh Shah8e7561c2005-04-28 00:25:56 -0700381 if (bridge->type != BRIDGE_TYPE_HOST) {
MUNEDA Takahiro551bcb72006-03-22 14:49:20 +0900382 if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
383 status = acpi_remove_notify_handler(bridge->func->handle,
384 ACPI_SYSTEM_NOTIFY,
385 handle_hotplug_event_func);
386 if (ACPI_FAILURE(status))
387 err("failed to remove notify handler\n");
388 }
Rajesh Shah8e7561c2005-04-28 00:25:56 -0700389 status = acpi_install_notify_handler(bridge->handle,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 ACPI_SYSTEM_NOTIFY,
391 handle_hotplug_event_bridge,
392 bridge);
393
Rajesh Shah8e7561c2005-04-28 00:25:56 -0700394 if (ACPI_FAILURE(status)) {
395 err("failed to register interrupt notify handler\n");
396 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398}
399
400
MUNEDA Takahiro551bcb72006-03-22 14:49:20 +0900401/* find acpiphp_func from acpiphp_bridge */
402static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle)
403{
404 struct list_head *node, *l;
405 struct acpiphp_bridge *bridge;
406 struct acpiphp_slot *slot;
407 struct acpiphp_func *func;
408
409 list_for_each(node, &bridge_list) {
410 bridge = list_entry(node, struct acpiphp_bridge, list);
411 for (slot = bridge->slots; slot; slot = slot->next) {
412 list_for_each(l, &slot->funcs) {
413 func = list_entry(l, struct acpiphp_func,
414 sibling);
415 if (func->handle == handle)
416 return func;
417 }
418 }
419 }
420
421 return NULL;
422}
423
424
425static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge)
426{
427 acpi_handle dummy_handle;
428
429 if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
430 "_STA", &dummy_handle)))
431 bridge->flags |= BRIDGE_HAS_STA;
432
433 if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
434 "_EJ0", &dummy_handle)))
435 bridge->flags |= BRIDGE_HAS_EJ0;
436
437 if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
438 "_PS0", &dummy_handle)))
439 bridge->flags |= BRIDGE_HAS_PS0;
440
441 if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
442 "_PS3", &dummy_handle)))
443 bridge->flags |= BRIDGE_HAS_PS3;
444
445 /* is this ejectable p2p bridge? */
446 if (bridge->flags & BRIDGE_HAS_EJ0) {
447 struct acpiphp_func *func;
448
449 dbg("found ejectable p2p bridge\n");
450
451 /* make link between PCI bridge and PCI function */
452 func = acpiphp_bridge_handle_to_function(bridge->handle);
453 if (!func)
454 return;
455 bridge->func = func;
456 func->bridge = bridge;
457 }
458}
459
460
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461/* allocate and initialize host bridge data structure */
Rajesh Shah42f49a62005-04-28 00:25:53 -0700462static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 struct acpiphp_bridge *bridge;
465
Eric Sesterhennf5afe802006-02-28 15:34:49 +0100466 bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 if (bridge == NULL)
468 return;
469
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 bridge->type = BRIDGE_TYPE_HOST;
471 bridge->handle = handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472
Rajesh Shah42f49a62005-04-28 00:25:53 -0700473 bridge->pci_bus = pci_bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474
475 spin_lock_init(&bridge->res_lock);
476
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 init_bridge_misc(bridge);
478}
479
480
481/* allocate and initialize PCI-to-PCI bridge data structure */
Rajesh Shah42f49a62005-04-28 00:25:53 -0700482static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483{
484 struct acpiphp_bridge *bridge;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Eric Sesterhennf5afe802006-02-28 15:34:49 +0100486 bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 if (bridge == NULL) {
488 err("out of memory\n");
489 return;
490 }
491
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 bridge->type = BRIDGE_TYPE_P2P;
493 bridge->handle = handle;
MUNEDA Takahiro551bcb72006-03-22 14:49:20 +0900494 config_p2p_bridge_flags(bridge);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495
Rajesh Shah42f49a62005-04-28 00:25:53 -0700496 bridge->pci_dev = pci_dev_get(pci_dev);
497 bridge->pci_bus = pci_dev->subordinate;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 if (!bridge->pci_bus) {
499 err("This is not a PCI-to-PCI bridge!\n");
Rajesh Shah42f49a62005-04-28 00:25:53 -0700500 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 }
502
503 spin_lock_init(&bridge->res_lock);
504
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 init_bridge_misc(bridge);
Rajesh Shah42f49a62005-04-28 00:25:53 -0700506 return;
507 err:
508 pci_dev_put(pci_dev);
509 kfree(bridge);
510 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511}
512
513
514/* callback routine to find P2P bridges */
515static acpi_status
516find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
517{
518 acpi_status status;
519 acpi_handle dummy_handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 unsigned long tmp;
Rajesh Shah42f49a62005-04-28 00:25:53 -0700521 int device, function;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 struct pci_dev *dev;
Rajesh Shah42f49a62005-04-28 00:25:53 -0700523 struct pci_bus *pci_bus = context;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
525 status = acpi_get_handle(handle, "_ADR", &dummy_handle);
526 if (ACPI_FAILURE(status))
527 return AE_OK; /* continue */
528
529 status = acpi_evaluate_integer(handle, "_ADR", NULL, &tmp);
530 if (ACPI_FAILURE(status)) {
531 dbg("%s: _ADR evaluation failure\n", __FUNCTION__);
532 return AE_OK;
533 }
534
535 device = (tmp >> 16) & 0xffff;
536 function = tmp & 0xffff;
537
Rajesh Shah42f49a62005-04-28 00:25:53 -0700538 dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539
Rajesh Shah42f49a62005-04-28 00:25:53 -0700540 if (!dev || !dev->subordinate)
541 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542
543 /* check if this bridge has ejectable slots */
Kristen Accardi4e8662b2006-06-28 03:08:06 -0400544 if ((detect_ejectable_slots(handle) > 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
Rajesh Shah42f49a62005-04-28 00:25:53 -0700546 add_p2p_bridge(handle, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 }
548
Kenji Kaneshige7c8f25d2006-02-27 22:15:49 +0900549 /* search P2P bridges under this p2p bridge */
550 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
551 find_p2p_bridge, dev->subordinate, NULL);
552 if (ACPI_FAILURE(status))
MUNEDA Takahiro551bcb72006-03-22 14:49:20 +0900553 warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
Kenji Kaneshige7c8f25d2006-02-27 22:15:49 +0900554
Rajesh Shah42f49a62005-04-28 00:25:53 -0700555 out:
556 pci_dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 return AE_OK;
558}
559
560
561/* find hot-pluggable slots, and then find P2P bridge */
562static int add_bridge(acpi_handle handle)
563{
564 acpi_status status;
565 unsigned long tmp;
566 int seg, bus;
567 acpi_handle dummy_handle;
Rajesh Shah42f49a62005-04-28 00:25:53 -0700568 struct pci_bus *pci_bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
570 /* if the bridge doesn't have _STA, we assume it is always there */
571 status = acpi_get_handle(handle, "_STA", &dummy_handle);
572 if (ACPI_SUCCESS(status)) {
573 status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp);
574 if (ACPI_FAILURE(status)) {
575 dbg("%s: _STA evaluation failure\n", __FUNCTION__);
576 return 0;
577 }
578 if ((tmp & ACPI_STA_FUNCTIONING) == 0)
579 /* don't register this object */
580 return 0;
581 }
582
583 /* get PCI segment number */
584 status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp);
585
586 seg = ACPI_SUCCESS(status) ? tmp : 0;
587
588 /* get PCI bus number */
589 status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp);
590
591 if (ACPI_SUCCESS(status)) {
592 bus = tmp;
593 } else {
594 warn("can't get bus number, assuming 0\n");
595 bus = 0;
596 }
597
Rajesh Shah42f49a62005-04-28 00:25:53 -0700598 pci_bus = pci_find_bus(seg, bus);
599 if (!pci_bus) {
600 err("Can't find bus %04x:%02x\n", seg, bus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 return 0;
602 }
603
Rajesh Shah42f49a62005-04-28 00:25:53 -0700604 /* check if this bridge has ejectable slots */
605 if (detect_ejectable_slots(handle) > 0) {
606 dbg("found PCI host-bus bridge with hot-pluggable slots\n");
607 add_host_bridge(handle, pci_bus);
Rajesh Shah42f49a62005-04-28 00:25:53 -0700608 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
610 /* search P2P bridges under this host bridge */
611 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
Rajesh Shah42f49a62005-04-28 00:25:53 -0700612 find_p2p_bridge, pci_bus, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
614 if (ACPI_FAILURE(status))
MUNEDA Takahiro551bcb72006-03-22 14:49:20 +0900615 warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616
617 return 0;
618}
619
Rajesh Shah42f49a62005-04-28 00:25:53 -0700620static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
621{
622 struct list_head *head;
623 list_for_each(head, &bridge_list) {
624 struct acpiphp_bridge *bridge = list_entry(head,
625 struct acpiphp_bridge, list);
626 if (bridge->handle == handle)
627 return bridge;
628 }
629
630 return NULL;
631}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
Rajesh Shah364d5092005-04-28 00:25:54 -0700633static void cleanup_bridge(struct acpiphp_bridge *bridge)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634{
Rajesh Shah42f49a62005-04-28 00:25:53 -0700635 struct list_head *list, *tmp;
Rajesh Shah42f49a62005-04-28 00:25:53 -0700636 struct acpiphp_slot *slot;
637 acpi_status status;
Rajesh Shah364d5092005-04-28 00:25:54 -0700638 acpi_handle handle = bridge->handle;
Rajesh Shah42f49a62005-04-28 00:25:53 -0700639
640 status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
641 handle_hotplug_event_bridge);
642 if (ACPI_FAILURE(status))
643 err("failed to remove notify handler\n");
644
MUNEDA Takahiro551bcb72006-03-22 14:49:20 +0900645 if ((bridge->type != BRIDGE_TYPE_HOST) &&
646 ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) {
647 status = acpi_install_notify_handler(bridge->func->handle,
648 ACPI_SYSTEM_NOTIFY,
649 handle_hotplug_event_func,
650 bridge->func);
651 if (ACPI_FAILURE(status))
652 err("failed to install interrupt notify handler\n");
653 }
654
Rajesh Shah42f49a62005-04-28 00:25:53 -0700655 slot = bridge->slots;
656 while (slot) {
657 struct acpiphp_slot *next = slot->next;
658 list_for_each_safe (list, tmp, &slot->funcs) {
659 struct acpiphp_func *func;
660 func = list_entry(list, struct acpiphp_func, sibling);
Kristen Accardi4e8662b2006-06-28 03:08:06 -0400661 if (is_dock_device(func->handle)) {
662 unregister_hotplug_dock_device(func->handle);
663 unregister_dock_notifier(&func->nb);
664 }
Kristen Accardi20416ea2006-02-23 17:56:03 -0800665 if (!(func->flags & FUNC_HAS_DCK)) {
666 status = acpi_remove_notify_handler(func->handle,
Rajesh Shah42f49a62005-04-28 00:25:53 -0700667 ACPI_SYSTEM_NOTIFY,
668 handle_hotplug_event_func);
Kristen Accardi20416ea2006-02-23 17:56:03 -0800669 if (ACPI_FAILURE(status))
670 err("failed to remove notify handler\n");
671 }
Rajesh Shah42f49a62005-04-28 00:25:53 -0700672 pci_dev_put(func->pci_dev);
673 list_del(list);
674 kfree(func);
675 }
MUNEDA Takahiroe27da382006-02-23 17:56:08 -0800676 acpiphp_unregister_hotplug_slot(slot);
677 list_del(&slot->funcs);
Rajesh Shah42f49a62005-04-28 00:25:53 -0700678 kfree(slot);
679 slot = next;
680 }
681
682 pci_dev_put(bridge->pci_dev);
683 list_del(&bridge->list);
684 kfree(bridge);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685}
686
Rajesh Shah364d5092005-04-28 00:25:54 -0700687static acpi_status
688cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
689{
690 struct acpiphp_bridge *bridge;
691
MUNEDA Takahiro551bcb72006-03-22 14:49:20 +0900692 /* cleanup p2p bridges under this P2P bridge
693 in a depth-first manner */
694 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
695 cleanup_p2p_bridge, NULL, NULL);
696
Rajesh Shah364d5092005-04-28 00:25:54 -0700697 if (!(bridge = acpiphp_handle_to_bridge(handle)))
698 return AE_OK;
699 cleanup_bridge(bridge);
700 return AE_OK;
701}
702
703static void remove_bridge(acpi_handle handle)
704{
705 struct acpiphp_bridge *bridge;
706
MUNEDA Takahiro551bcb72006-03-22 14:49:20 +0900707 /* cleanup p2p bridges under this host bridge
708 in a depth-first manner */
709 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
710 (u32)1, cleanup_p2p_bridge, NULL, NULL);
711
Rajesh Shah364d5092005-04-28 00:25:54 -0700712 bridge = acpiphp_handle_to_bridge(handle);
MUNEDA Takahiro551bcb72006-03-22 14:49:20 +0900713 if (bridge)
Rajesh Shah364d5092005-04-28 00:25:54 -0700714 cleanup_bridge(bridge);
Rajesh Shah364d5092005-04-28 00:25:54 -0700715}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
Kenji Kaneshigea0d399a2005-04-28 00:25:59 -0700717static struct pci_dev * get_apic_pci_info(acpi_handle handle)
718{
719 struct acpi_pci_id id;
720 struct pci_bus *bus;
721 struct pci_dev *dev;
722
723 if (ACPI_FAILURE(acpi_get_pci_id(handle, &id)))
724 return NULL;
725
726 bus = pci_find_bus(id.segment, id.bus);
727 if (!bus)
728 return NULL;
729
730 dev = pci_get_slot(bus, PCI_DEVFN(id.device, id.function));
731 if (!dev)
732 return NULL;
733
734 if ((dev->class != PCI_CLASS_SYSTEM_PIC_IOAPIC) &&
735 (dev->class != PCI_CLASS_SYSTEM_PIC_IOXAPIC))
736 {
737 pci_dev_put(dev);
738 return NULL;
739 }
740
741 return dev;
742}
743
744static int get_gsi_base(acpi_handle handle, u32 *gsi_base)
745{
746 acpi_status status;
747 int result = -1;
748 unsigned long gsb;
749 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
750 union acpi_object *obj;
751 void *table;
752
753 status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
754 if (ACPI_SUCCESS(status)) {
755 *gsi_base = (u32)gsb;
756 return 0;
757 }
758
759 status = acpi_evaluate_object(handle, "_MAT", NULL, &buffer);
760 if (ACPI_FAILURE(status) || !buffer.length || !buffer.pointer)
761 return -1;
762
763 obj = buffer.pointer;
764 if (obj->type != ACPI_TYPE_BUFFER)
765 goto out;
766
767 table = obj->buffer.pointer;
768 switch (((acpi_table_entry_header *)table)->type) {
769 case ACPI_MADT_IOSAPIC:
770 *gsi_base = ((struct acpi_table_iosapic *)table)->global_irq_base;
771 result = 0;
772 break;
773 case ACPI_MADT_IOAPIC:
774 *gsi_base = ((struct acpi_table_ioapic *)table)->global_irq_base;
775 result = 0;
776 break;
777 default:
778 break;
779 }
780 out:
Kristen Accardi81b26bc2006-04-18 14:36:43 -0700781 kfree(buffer.pointer);
Kenji Kaneshigea0d399a2005-04-28 00:25:59 -0700782 return result;
783}
784
785static acpi_status
786ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)
787{
788 acpi_status status;
789 unsigned long sta;
790 acpi_handle tmp;
791 struct pci_dev *pdev;
792 u32 gsi_base;
793 u64 phys_addr;
794
795 /* Evaluate _STA if present */
796 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
797 if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL)
798 return AE_CTRL_DEPTH;
799
800 /* Scan only PCI bus scope */
801 status = acpi_get_handle(handle, "_HID", &tmp);
802 if (ACPI_SUCCESS(status))
803 return AE_CTRL_DEPTH;
804
805 if (get_gsi_base(handle, &gsi_base))
806 return AE_OK;
807
808 pdev = get_apic_pci_info(handle);
809 if (!pdev)
810 return AE_OK;
811
812 if (pci_enable_device(pdev)) {
813 pci_dev_put(pdev);
814 return AE_OK;
815 }
816
817 pci_set_master(pdev);
818
819 if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)")) {
820 pci_disable_device(pdev);
821 pci_dev_put(pdev);
822 return AE_OK;
823 }
824
825 phys_addr = pci_resource_start(pdev, 0);
826 if (acpi_register_ioapic(handle, phys_addr, gsi_base)) {
827 pci_release_region(pdev, 0);
828 pci_disable_device(pdev);
829 pci_dev_put(pdev);
830 return AE_OK;
831 }
832
833 return AE_OK;
834}
835
836static int acpiphp_configure_ioapics(acpi_handle handle)
837{
838 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
839 ACPI_UINT32_MAX, ioapic_add, NULL, NULL);
840 return 0;
841}
842
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843static int power_on_slot(struct acpiphp_slot *slot)
844{
845 acpi_status status;
846 struct acpiphp_func *func;
847 struct list_head *l;
848 int retval = 0;
849
850 /* if already enabled, just skip */
851 if (slot->flags & SLOT_POWEREDON)
852 goto err_exit;
853
854 list_for_each (l, &slot->funcs) {
855 func = list_entry(l, struct acpiphp_func, sibling);
856
857 if (func->flags & FUNC_HAS_PS0) {
858 dbg("%s: executing _PS0\n", __FUNCTION__);
859 status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
860 if (ACPI_FAILURE(status)) {
861 warn("%s: _PS0 failed\n", __FUNCTION__);
862 retval = -1;
863 goto err_exit;
864 } else
865 break;
866 }
867 }
868
869 /* TBD: evaluate _STA to check if the slot is enabled */
870
871 slot->flags |= SLOT_POWEREDON;
872
873 err_exit:
874 return retval;
875}
876
877
878static int power_off_slot(struct acpiphp_slot *slot)
879{
880 acpi_status status;
881 struct acpiphp_func *func;
882 struct list_head *l;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
884 int retval = 0;
885
886 /* if already disabled, just skip */
887 if ((slot->flags & SLOT_POWEREDON) == 0)
888 goto err_exit;
889
890 list_for_each (l, &slot->funcs) {
891 func = list_entry(l, struct acpiphp_func, sibling);
892
Rajesh Shah2f523b12005-04-28 00:25:55 -0700893 if (func->flags & FUNC_HAS_PS3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
895 if (ACPI_FAILURE(status)) {
896 warn("%s: _PS3 failed\n", __FUNCTION__);
897 retval = -1;
898 goto err_exit;
899 } else
900 break;
901 }
902 }
903
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 /* TBD: evaluate _STA to check if the slot is disabled */
905
906 slot->flags &= (~SLOT_POWEREDON);
907
908 err_exit:
909 return retval;
910}
911
912
Kristen Accardi15a1ae72006-02-23 17:55:58 -0800913
914/**
915 * acpiphp_max_busnr - return the highest reserved bus number under
916 * the given bus.
917 * @bus: bus to start search with
918 *
919 */
920static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
921{
922 struct list_head *tmp;
923 unsigned char max, n;
924
925 /*
926 * pci_bus_max_busnr will return the highest
927 * reserved busnr for all these children.
928 * that is equivalent to the bus->subordinate
929 * value. We don't want to use the parent's
930 * bus->subordinate value because it could have
931 * padding in it.
932 */
933 max = bus->secondary;
934
935 list_for_each(tmp, &bus->children) {
936 n = pci_bus_max_busnr(pci_bus_b(tmp));
937 if (n > max)
938 max = n;
939 }
940 return max;
941}
942
943
Kristen Accardi15a1ae72006-02-23 17:55:58 -0800944/**
945 * acpiphp_bus_add - add a new bus to acpi subsystem
946 * @func: acpiphp_func of the bridge
947 *
948 */
949static int acpiphp_bus_add(struct acpiphp_func *func)
950{
951 acpi_handle phandle;
952 struct acpi_device *device, *pdevice;
953 int ret_val;
954
955 acpi_get_parent(func->handle, &phandle);
956 if (acpi_bus_get_device(phandle, &pdevice)) {
957 dbg("no parent device, assuming NULL\n");
958 pdevice = NULL;
959 }
Kristen Accardi20416ea2006-02-23 17:56:03 -0800960 if (!acpi_bus_get_device(func->handle, &device)) {
961 dbg("bus exists... trim\n");
962 /* this shouldn't be in here, so remove
963 * the bus then re-add it...
964 */
965 ret_val = acpi_bus_trim(device, 1);
966 dbg("acpi_bus_trim return %x\n", ret_val);
967 }
968
969 ret_val = acpi_bus_add(&device, pdevice, func->handle,
970 ACPI_BUS_TYPE_DEVICE);
971 if (ret_val) {
972 dbg("error adding bus, %x\n",
973 -ret_val);
974 goto acpiphp_bus_add_out;
Kristen Accardi15a1ae72006-02-23 17:55:58 -0800975 }
976 /*
977 * try to start anyway. We could have failed to add
978 * simply because this bus had previously been added
979 * on another add. Don't bother with the return value
980 * we just keep going.
981 */
982 ret_val = acpi_bus_start(device);
983
984acpiphp_bus_add_out:
985 return ret_val;
986}
987
988
MUNEDA Takahiro92c9be92006-03-22 14:49:09 +0900989/**
990 * acpiphp_bus_trim - trim a bus from acpi subsystem
991 * @handle: handle to acpi namespace
992 *
993 */
994int acpiphp_bus_trim(acpi_handle handle)
995{
996 struct acpi_device *device;
997 int retval;
998
999 retval = acpi_bus_get_device(handle, &device);
1000 if (retval) {
1001 dbg("acpi_device not found\n");
1002 return retval;
1003 }
1004
1005 retval = acpi_bus_trim(device, 1);
1006 if (retval)
1007 err("cannot remove from acpi list\n");
1008
1009 return retval;
1010}
Kristen Accardi15a1ae72006-02-23 17:55:58 -08001011
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012/**
1013 * enable_device - enable, configure a slot
1014 * @slot: slot to be enabled
1015 *
1016 * This function should be called per *physical slot*,
1017 * not per each slot object in ACPI namespace.
1018 *
1019 */
1020static int enable_device(struct acpiphp_slot *slot)
1021{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 struct pci_dev *dev;
Rajesh Shah42f49a62005-04-28 00:25:53 -07001023 struct pci_bus *bus = slot->bridge->pci_bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 struct list_head *l;
1025 struct acpiphp_func *func;
1026 int retval = 0;
Rajesh Shah42f49a62005-04-28 00:25:53 -07001027 int num, max, pass;
MUNEDA Takahiro551bcb72006-03-22 14:49:20 +09001028 acpi_status status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
1030 if (slot->flags & SLOT_ENABLED)
1031 goto err_exit;
1032
1033 /* sanity check: dev should be NULL when hot-plugged in */
Rajesh Shah42f49a62005-04-28 00:25:53 -07001034 dev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 if (dev) {
1036 /* This case shouldn't happen */
1037 err("pci_dev structure already exists.\n");
Rajesh Shah42f49a62005-04-28 00:25:53 -07001038 pci_dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 retval = -1;
1040 goto err_exit;
1041 }
1042
Rajesh Shah42f49a62005-04-28 00:25:53 -07001043 num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));
1044 if (num == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 err("No new device found\n");
1046 retval = -1;
1047 goto err_exit;
1048 }
1049
Kristen Accardi15a1ae72006-02-23 17:55:58 -08001050 max = acpiphp_max_busnr(bus);
Rajesh Shah42f49a62005-04-28 00:25:53 -07001051 for (pass = 0; pass < 2; pass++) {
1052 list_for_each_entry(dev, &bus->devices, bus_list) {
1053 if (PCI_SLOT(dev->devfn) != slot->device)
1054 continue;
1055 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
Kristen Accardic64b5ee2005-12-14 09:37:26 -08001056 dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
Rajesh Shah42f49a62005-04-28 00:25:53 -07001057 max = pci_scan_bridge(bus, dev, max, pass);
MUNEDA Takahiro92c9be92006-03-22 14:49:09 +09001058 if (pass && dev->subordinate)
Kristen Accardic64b5ee2005-12-14 09:37:26 -08001059 pci_bus_size_bridges(dev->subordinate);
1060 }
Rajesh Shah42f49a62005-04-28 00:25:53 -07001061 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 }
1063
MUNEDA Takahiro92c9be92006-03-22 14:49:09 +09001064 list_for_each (l, &slot->funcs) {
1065 func = list_entry(l, struct acpiphp_func, sibling);
1066 acpiphp_bus_add(func);
1067 }
1068
Rajesh Shah42f49a62005-04-28 00:25:53 -07001069 pci_bus_assign_resources(bus);
Kristen Accardi8e5dce32005-10-18 17:21:40 -07001070 acpiphp_sanitize_bus(bus);
1071 pci_enable_bridges(bus);
Rajesh Shah42f49a62005-04-28 00:25:53 -07001072 pci_bus_add_devices(bus);
MUNEDA Takahiro0cccd0c2006-02-24 17:46:04 +09001073 acpiphp_set_hpp_values(slot->bridge->handle, bus);
1074 acpiphp_configure_ioapics(slot->bridge->handle);
Rajesh Shah42f49a62005-04-28 00:25:53 -07001075
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 /* associate pci_dev to our representation */
1077 list_for_each (l, &slot->funcs) {
1078 func = list_entry(l, struct acpiphp_func, sibling);
Rajesh Shah42f49a62005-04-28 00:25:53 -07001079 func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 func->function));
MUNEDA Takahiro551bcb72006-03-22 14:49:20 +09001081 if (!func->pci_dev)
1082 continue;
1083
1084 if (func->pci_dev->hdr_type != PCI_HEADER_TYPE_BRIDGE &&
1085 func->pci_dev->hdr_type != PCI_HEADER_TYPE_CARDBUS)
1086 continue;
1087
1088 status = find_p2p_bridge(func->handle, (u32)1, bus, NULL);
1089 if (ACPI_FAILURE(status))
1090 warn("find_p2p_bridge failed (error code = 0x%x)\n",
1091 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 }
1093
1094 slot->flags |= SLOT_ENABLED;
1095
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 err_exit:
1097 return retval;
1098}
1099
1100
1101/**
1102 * disable_device - disable a slot
1103 */
1104static int disable_device(struct acpiphp_slot *slot)
1105{
1106 int retval = 0;
1107 struct acpiphp_func *func;
1108 struct list_head *l;
1109
1110 /* is this slot already disabled? */
1111 if (!(slot->flags & SLOT_ENABLED))
1112 goto err_exit;
1113
1114 list_for_each (l, &slot->funcs) {
1115 func = list_entry(l, struct acpiphp_func, sibling);
MUNEDA Takahiro92c9be92006-03-22 14:49:09 +09001116
MUNEDA Takahiro551bcb72006-03-22 14:49:20 +09001117 if (func->bridge) {
1118 /* cleanup p2p bridges under this P2P bridge */
1119 cleanup_p2p_bridge(func->bridge->handle,
1120 (u32)1, NULL, NULL);
1121 func->bridge = NULL;
1122 }
1123
MUNEDA Takahiro92c9be92006-03-22 14:49:09 +09001124 acpiphp_bus_trim(func->handle);
1125 /* try to remove anyway.
1126 * acpiphp_bus_add might have been failed */
1127
Rajesh Shah42f49a62005-04-28 00:25:53 -07001128 if (!func->pci_dev)
1129 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130
Rajesh Shah42f49a62005-04-28 00:25:53 -07001131 pci_remove_bus_device(func->pci_dev);
1132 pci_dev_put(func->pci_dev);
1133 func->pci_dev = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 }
1135
1136 slot->flags &= (~SLOT_ENABLED);
1137
1138 err_exit:
1139 return retval;
1140}
1141
1142
1143/**
1144 * get_slot_status - get ACPI slot status
1145 *
1146 * if a slot has _STA for each function and if any one of them
1147 * returned non-zero status, return it
1148 *
1149 * if a slot doesn't have _STA and if any one of its functions'
1150 * configuration space is configured, return 0x0f as a _STA
1151 *
1152 * otherwise return 0
1153 */
1154static unsigned int get_slot_status(struct acpiphp_slot *slot)
1155{
1156 acpi_status status;
1157 unsigned long sta = 0;
1158 u32 dvid;
1159 struct list_head *l;
1160 struct acpiphp_func *func;
1161
1162 list_for_each (l, &slot->funcs) {
1163 func = list_entry(l, struct acpiphp_func, sibling);
1164
1165 if (func->flags & FUNC_HAS_STA) {
1166 status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta);
1167 if (ACPI_SUCCESS(status) && sta)
1168 break;
1169 } else {
1170 pci_bus_read_config_dword(slot->bridge->pci_bus,
1171 PCI_DEVFN(slot->device,
1172 func->function),
1173 PCI_VENDOR_ID, &dvid);
1174 if (dvid != 0xffffffff) {
1175 sta = ACPI_STA_ALL;
1176 break;
1177 }
1178 }
1179 }
1180
1181 return (unsigned int)sta;
1182}
1183
1184/**
Rajesh Shah8d50e332005-04-28 00:25:57 -07001185 * acpiphp_eject_slot - physically eject the slot
1186 */
1187static int acpiphp_eject_slot(struct acpiphp_slot *slot)
1188{
1189 acpi_status status;
1190 struct acpiphp_func *func;
1191 struct list_head *l;
1192 struct acpi_object_list arg_list;
1193 union acpi_object arg;
1194
1195 list_for_each (l, &slot->funcs) {
1196 func = list_entry(l, struct acpiphp_func, sibling);
1197
1198 /* We don't want to call _EJ0 on non-existing functions. */
1199 if ((func->flags & FUNC_HAS_EJ0)) {
1200 /* _EJ0 method take one argument */
1201 arg_list.count = 1;
1202 arg_list.pointer = &arg;
1203 arg.type = ACPI_TYPE_INTEGER;
1204 arg.integer.value = 1;
1205
1206 status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
1207 if (ACPI_FAILURE(status)) {
1208 warn("%s: _EJ0 failed\n", __FUNCTION__);
1209 return -1;
1210 } else
1211 break;
1212 }
1213 }
1214 return 0;
1215}
1216
1217/**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 * acpiphp_check_bridge - re-enumerate devices
1219 *
1220 * Iterate over all slots under this bridge and make sure that if a
1221 * card is present they are enabled, and if not they are disabled.
1222 */
1223static int acpiphp_check_bridge(struct acpiphp_bridge *bridge)
1224{
1225 struct acpiphp_slot *slot;
1226 int retval = 0;
1227 int enabled, disabled;
1228
1229 enabled = disabled = 0;
1230
1231 for (slot = bridge->slots; slot; slot = slot->next) {
1232 unsigned int status = get_slot_status(slot);
1233 if (slot->flags & SLOT_ENABLED) {
1234 if (status == ACPI_STA_ALL)
1235 continue;
1236 retval = acpiphp_disable_slot(slot);
1237 if (retval) {
1238 err("Error occurred in disabling\n");
1239 goto err_exit;
Rajesh Shah8d50e332005-04-28 00:25:57 -07001240 } else {
1241 acpiphp_eject_slot(slot);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 }
1243 disabled++;
1244 } else {
1245 if (status != ACPI_STA_ALL)
1246 continue;
1247 retval = acpiphp_enable_slot(slot);
1248 if (retval) {
1249 err("Error occurred in enabling\n");
1250 goto err_exit;
1251 }
1252 enabled++;
1253 }
1254 }
1255
1256 dbg("%s: %d enabled, %d disabled\n", __FUNCTION__, enabled, disabled);
1257
1258 err_exit:
1259 return retval;
1260}
1261
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001262static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
1263{
1264 u16 pci_cmd, pci_bctl;
1265 struct pci_dev *cdev;
1266
1267 /* Program hpp values for this device */
1268 if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
1269 (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
1270 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
1271 return;
Kenji Kaneshigee22b73502006-05-02 10:57:14 +09001272
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001273 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
Kenji Kaneshigee22b73502006-05-02 10:57:14 +09001274 bridge->hpp.t0->cache_line_size);
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001275 pci_write_config_byte(dev, PCI_LATENCY_TIMER,
Kenji Kaneshigee22b73502006-05-02 10:57:14 +09001276 bridge->hpp.t0->latency_timer);
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001277 pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
Kenji Kaneshigee22b73502006-05-02 10:57:14 +09001278 if (bridge->hpp.t0->enable_serr)
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001279 pci_cmd |= PCI_COMMAND_SERR;
1280 else
1281 pci_cmd &= ~PCI_COMMAND_SERR;
Kenji Kaneshigee22b73502006-05-02 10:57:14 +09001282 if (bridge->hpp.t0->enable_perr)
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001283 pci_cmd |= PCI_COMMAND_PARITY;
1284 else
1285 pci_cmd &= ~PCI_COMMAND_PARITY;
1286 pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
1287
1288 /* Program bridge control value and child devices */
1289 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
1290 pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
Kenji Kaneshigee22b73502006-05-02 10:57:14 +09001291 bridge->hpp.t0->latency_timer);
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001292 pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
Kenji Kaneshigee22b73502006-05-02 10:57:14 +09001293 if (bridge->hpp.t0->enable_serr)
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001294 pci_bctl |= PCI_BRIDGE_CTL_SERR;
1295 else
1296 pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
Kenji Kaneshigee22b73502006-05-02 10:57:14 +09001297 if (bridge->hpp.t0->enable_perr)
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001298 pci_bctl |= PCI_BRIDGE_CTL_PARITY;
1299 else
1300 pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
1301 pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
1302 if (dev->subordinate) {
1303 list_for_each_entry(cdev, &dev->subordinate->devices,
1304 bus_list)
1305 program_hpp(cdev, bridge);
1306 }
1307 }
1308}
1309
1310static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus)
1311{
1312 struct acpiphp_bridge bridge;
1313 struct pci_dev *dev;
1314
1315 memset(&bridge, 0, sizeof(bridge));
1316 bridge.handle = handle;
Kenji Kaneshige7430e342006-05-02 10:54:50 +09001317 bridge.pci_bus = bus;
Kristen Accardi783c49f2006-03-03 10:16:05 -08001318 bridge.pci_dev = bus->self;
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001319 decode_hpp(&bridge);
1320 list_for_each_entry(dev, &bus->devices, bus_list)
1321 program_hpp(dev, &bridge);
1322
1323}
1324
1325/*
1326 * Remove devices for which we could not assign resources, call
1327 * arch specific code to fix-up the bus
1328 */
1329static void acpiphp_sanitize_bus(struct pci_bus *bus)
1330{
1331 struct pci_dev *dev;
1332 int i;
1333 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
1334
1335 list_for_each_entry(dev, &bus->devices, bus_list) {
1336 for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {
1337 struct resource *res = &dev->resource[i];
1338 if ((res->flags & type_mask) && !res->start &&
1339 res->end) {
1340 /* Could not assign a required resources
1341 * for this device, remove it */
1342 pci_remove_bus_device(dev);
1343 break;
1344 }
1345 }
1346 }
1347}
1348
1349/* Program resources in newly inserted bridge */
1350static int acpiphp_configure_bridge (acpi_handle handle)
1351{
1352 struct acpi_pci_id pci_id;
1353 struct pci_bus *bus;
1354
1355 if (ACPI_FAILURE(acpi_get_pci_id(handle, &pci_id))) {
1356 err("cannot get PCI domain and bus number for bridge\n");
1357 return -EINVAL;
1358 }
1359 bus = pci_find_bus(pci_id.segment, pci_id.bus);
1360 if (!bus) {
1361 err("cannot find bus %d:%d\n",
1362 pci_id.segment, pci_id.bus);
1363 return -EINVAL;
1364 }
1365
1366 pci_bus_size_bridges(bus);
1367 pci_bus_assign_resources(bus);
1368 acpiphp_sanitize_bus(bus);
1369 acpiphp_set_hpp_values(handle, bus);
1370 pci_enable_bridges(bus);
Kenji Kaneshigea0d399a2005-04-28 00:25:59 -07001371 acpiphp_configure_ioapics(handle);
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001372 return 0;
1373}
1374
1375static void handle_bridge_insertion(acpi_handle handle, u32 type)
1376{
1377 struct acpi_device *device, *pdevice;
1378 acpi_handle phandle;
1379
1380 if ((type != ACPI_NOTIFY_BUS_CHECK) &&
1381 (type != ACPI_NOTIFY_DEVICE_CHECK)) {
1382 err("unexpected notification type %d\n", type);
1383 return;
1384 }
1385
1386 acpi_get_parent(handle, &phandle);
1387 if (acpi_bus_get_device(phandle, &pdevice)) {
1388 dbg("no parent device, assuming NULL\n");
1389 pdevice = NULL;
1390 }
1391 if (acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE)) {
1392 err("cannot add bridge to acpi list\n");
1393 return;
1394 }
1395 if (!acpiphp_configure_bridge(handle) &&
1396 !acpi_bus_start(device))
1397 add_bridge(handle);
1398 else
1399 err("cannot configure and start bridge\n");
1400
1401}
1402
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403/*
1404 * ACPI event handlers
1405 */
1406
1407/**
1408 * handle_hotplug_event_bridge - handle ACPI event on bridges
1409 *
1410 * @handle: Notify()'ed acpi_handle
1411 * @type: Notify code
1412 * @context: pointer to acpiphp_bridge structure
1413 *
1414 * handles ACPI event notification on {host,p2p} bridges
1415 *
1416 */
1417static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *context)
1418{
1419 struct acpiphp_bridge *bridge;
1420 char objname[64];
1421 struct acpi_buffer buffer = { .length = sizeof(objname),
1422 .pointer = objname };
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001423 struct acpi_device *device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001425 if (acpi_bus_get_device(handle, &device)) {
1426 /* This bridge must have just been physically inserted */
1427 handle_bridge_insertion(handle, type);
1428 return;
1429 }
1430
1431 bridge = acpiphp_handle_to_bridge(handle);
1432 if (!bridge) {
1433 err("cannot get bridge info\n");
1434 return;
1435 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436
1437 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
1438
1439 switch (type) {
1440 case ACPI_NOTIFY_BUS_CHECK:
1441 /* bus re-enumerate */
1442 dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
1443 acpiphp_check_bridge(bridge);
1444 break;
1445
1446 case ACPI_NOTIFY_DEVICE_CHECK:
1447 /* device check */
1448 dbg("%s: Device check notify on %s\n", __FUNCTION__, objname);
1449 acpiphp_check_bridge(bridge);
1450 break;
1451
1452 case ACPI_NOTIFY_DEVICE_WAKE:
1453 /* wake event */
1454 dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);
1455 break;
1456
1457 case ACPI_NOTIFY_EJECT_REQUEST:
1458 /* request device eject */
1459 dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
MUNEDA Takahiro551bcb72006-03-22 14:49:20 +09001460 if ((bridge->type != BRIDGE_TYPE_HOST) &&
1461 (bridge->flags & BRIDGE_HAS_EJ0)) {
1462 struct acpiphp_slot *slot;
1463 slot = bridge->func->slot;
1464 if (!acpiphp_disable_slot(slot))
1465 acpiphp_eject_slot(slot);
1466 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 break;
1468
1469 case ACPI_NOTIFY_FREQUENCY_MISMATCH:
1470 printk(KERN_ERR "Device %s cannot be configured due"
1471 " to a frequency mismatch\n", objname);
1472 break;
1473
1474 case ACPI_NOTIFY_BUS_MODE_MISMATCH:
1475 printk(KERN_ERR "Device %s cannot be configured due"
1476 " to a bus mode mismatch\n", objname);
1477 break;
1478
1479 case ACPI_NOTIFY_POWER_FAULT:
1480 printk(KERN_ERR "Device %s has suffered a power fault\n",
1481 objname);
1482 break;
1483
1484 default:
1485 warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
1486 break;
1487 }
1488}
1489
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490/**
1491 * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
1492 *
1493 * @handle: Notify()'ed acpi_handle
1494 * @type: Notify code
1495 * @context: pointer to acpiphp_func structure
1496 *
1497 * handles ACPI event notification on slots
1498 *
1499 */
Kristen Accardi20416ea2006-02-23 17:56:03 -08001500void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501{
1502 struct acpiphp_func *func;
1503 char objname[64];
1504 struct acpi_buffer buffer = { .length = sizeof(objname),
1505 .pointer = objname };
1506
1507 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
1508
1509 func = (struct acpiphp_func *)context;
1510
1511 switch (type) {
1512 case ACPI_NOTIFY_BUS_CHECK:
1513 /* bus re-enumerate */
1514 dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
1515 acpiphp_enable_slot(func->slot);
1516 break;
1517
1518 case ACPI_NOTIFY_DEVICE_CHECK:
1519 /* device check : re-enumerate from parent bus */
1520 dbg("%s: Device check notify on %s\n", __FUNCTION__, objname);
1521 acpiphp_check_bridge(func->slot->bridge);
1522 break;
1523
1524 case ACPI_NOTIFY_DEVICE_WAKE:
1525 /* wake event */
1526 dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);
1527 break;
1528
1529 case ACPI_NOTIFY_EJECT_REQUEST:
1530 /* request device eject */
1531 dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
Rajesh Shah8d50e332005-04-28 00:25:57 -07001532 if (!(acpiphp_disable_slot(func->slot)))
1533 acpiphp_eject_slot(func->slot);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 break;
1535
1536 default:
1537 warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
1538 break;
1539 }
1540}
1541
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001542
1543static acpi_status
1544find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
1545{
1546 int *count = (int *)context;
1547
Kristen Accardi783c49f2006-03-03 10:16:05 -08001548 if (acpi_root_bridge(handle)) {
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001549 acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
1550 handle_hotplug_event_bridge, NULL);
1551 (*count)++;
1552 }
1553 return AE_OK ;
1554}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
1556static struct acpi_pci_driver acpi_pci_hp_driver = {
1557 .add = add_bridge,
1558 .remove = remove_bridge,
1559};
1560
1561/**
1562 * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures
1563 *
1564 */
1565int __init acpiphp_glue_init(void)
1566{
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001567 int num = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001569 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
1570 ACPI_UINT32_MAX, find_root_bridges, &num, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571
1572 if (num <= 0)
1573 return -1;
Rajesh Shah8e7561c2005-04-28 00:25:56 -07001574 else
1575 acpi_pci_register_driver(&acpi_pci_hp_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576
1577 return 0;
1578}
1579
1580
1581/**
1582 * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures
1583 *
1584 * This function frees all data allocated in acpiphp_glue_init()
1585 */
1586void __exit acpiphp_glue_exit(void)
1587{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 acpi_pci_unregister_driver(&acpi_pci_hp_driver);
1589}
1590
1591
1592/**
1593 * acpiphp_get_num_slots - count number of slots in a system
1594 */
1595int __init acpiphp_get_num_slots(void)
1596{
1597 struct list_head *node;
1598 struct acpiphp_bridge *bridge;
1599 int num_slots;
1600
1601 num_slots = 0;
1602
1603 list_for_each (node, &bridge_list) {
1604 bridge = (struct acpiphp_bridge *)node;
Rajesh Shah42f49a62005-04-28 00:25:53 -07001605 dbg("Bus %04x:%02x has %d slot%s\n",
1606 pci_domain_nr(bridge->pci_bus),
1607 bridge->pci_bus->number, bridge->nr_slots,
1608 bridge->nr_slots == 1 ? "" : "s");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 num_slots += bridge->nr_slots;
1610 }
1611
Rajesh Shah42f49a62005-04-28 00:25:53 -07001612 dbg("Total %d slots\n", num_slots);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 return num_slots;
1614}
1615
1616
1617#if 0
1618/**
1619 * acpiphp_for_each_slot - call function for each slot
1620 * @fn: callback function
1621 * @data: context to be passed to callback function
1622 *
1623 */
1624static int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
1625{
1626 struct list_head *node;
1627 struct acpiphp_bridge *bridge;
1628 struct acpiphp_slot *slot;
1629 int retval = 0;
1630
1631 list_for_each (node, &bridge_list) {
1632 bridge = (struct acpiphp_bridge *)node;
1633 for (slot = bridge->slots; slot; slot = slot->next) {
1634 retval = fn(slot, data);
1635 if (!retval)
1636 goto err_exit;
1637 }
1638 }
1639
1640 err_exit:
1641 return retval;
1642}
1643#endif
1644
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645
1646/**
1647 * acpiphp_enable_slot - power on slot
1648 */
1649int acpiphp_enable_slot(struct acpiphp_slot *slot)
1650{
1651 int retval;
1652
Ingo Molnar6aa4cdd2006-01-13 16:02:15 +01001653 mutex_lock(&slot->crit_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654
1655 /* wake up all functions */
1656 retval = power_on_slot(slot);
1657 if (retval)
1658 goto err_exit;
1659
MUNEDA Takahirocde0e5d2006-03-22 14:49:33 +09001660 if (get_slot_status(slot) == ACPI_STA_ALL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 /* configure all functions */
1662 retval = enable_device(slot);
MUNEDA Takahirocde0e5d2006-03-22 14:49:33 +09001663 if (retval)
1664 power_off_slot(slot);
1665 } else {
1666 dbg("%s: Slot status is not ACPI_STA_ALL\n", __FUNCTION__);
1667 power_off_slot(slot);
1668 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669
1670 err_exit:
Ingo Molnar6aa4cdd2006-01-13 16:02:15 +01001671 mutex_unlock(&slot->crit_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 return retval;
1673}
1674
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675/**
1676 * acpiphp_disable_slot - power off slot
1677 */
1678int acpiphp_disable_slot(struct acpiphp_slot *slot)
1679{
1680 int retval = 0;
1681
Ingo Molnar6aa4cdd2006-01-13 16:02:15 +01001682 mutex_lock(&slot->crit_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683
1684 /* unconfigure all functions */
1685 retval = disable_device(slot);
1686 if (retval)
1687 goto err_exit;
1688
1689 /* power off all functions */
1690 retval = power_off_slot(slot);
1691 if (retval)
1692 goto err_exit;
1693
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 err_exit:
Ingo Molnar6aa4cdd2006-01-13 16:02:15 +01001695 mutex_unlock(&slot->crit_sect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 return retval;
1697}
1698
1699
1700/*
1701 * slot enabled: 1
1702 * slot disabled: 0
1703 */
1704u8 acpiphp_get_power_status(struct acpiphp_slot *slot)
1705{
Rajesh Shah8d50e332005-04-28 00:25:57 -07001706 return (slot->flags & SLOT_POWEREDON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707}
1708
1709
1710/*
1711 * latch closed: 1
1712 * latch open: 0
1713 */
1714u8 acpiphp_get_latch_status(struct acpiphp_slot *slot)
1715{
1716 unsigned int sta;
1717
1718 sta = get_slot_status(slot);
1719
1720 return (sta & ACPI_STA_SHOW_IN_UI) ? 1 : 0;
1721}
1722
1723
1724/*
1725 * adapter presence : 1
1726 * absence : 0
1727 */
1728u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot)
1729{
1730 unsigned int sta;
1731
1732 sta = get_slot_status(slot);
1733
1734 return (sta == 0) ? 0 : 1;
1735}
1736
1737
1738/*
1739 * pci address (seg/bus/dev)
1740 */
1741u32 acpiphp_get_address(struct acpiphp_slot *slot)
1742{
1743 u32 address;
Rajesh Shah42f49a62005-04-28 00:25:53 -07001744 struct pci_bus *pci_bus = slot->bridge->pci_bus;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745
Rajesh Shah42f49a62005-04-28 00:25:53 -07001746 address = (pci_domain_nr(pci_bus) << 16) |
1747 (pci_bus->number << 8) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 slot->device;
1749
1750 return address;
1751}