More meth updates.
[linux-2.6/linux-mips.git] / drivers / acpi / pci_link.c
blob8fab27afa9f94049640b1770d3538b6bc69d9e00
1 /*
2 * pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 34 $)
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6 * Copyright (C) 2002 Dominik Brodowski <devel@brodo.de>
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 * TBD:
27 * 1. Support more than one IRQ resource entry per link device (index).
28 * 2. Implement start/stop mechanism and use ACPI Bus Driver facilities
29 * for IRQ management (e.g. start()->_SRS).
32 #include <linux/kernel.h>
33 #include <linux/module.h>
34 #include <linux/init.h>
35 #include <linux/types.h>
36 #include <linux/proc_fs.h>
37 #include <linux/spinlock.h>
38 #include <linux/pm.h>
39 #include <linux/pci.h>
41 #include <acpi/acpi_bus.h>
42 #include <acpi/acpi_drivers.h>
45 #define _COMPONENT ACPI_PCI_COMPONENT
46 ACPI_MODULE_NAME ("pci_link")
48 #define ACPI_PCI_LINK_CLASS "pci_irq_routing"
49 #define ACPI_PCI_LINK_HID "PNP0C0F"
50 #define ACPI_PCI_LINK_DRIVER_NAME "ACPI PCI Interrupt Link Driver"
51 #define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link"
52 #define ACPI_PCI_LINK_FILE_INFO "info"
53 #define ACPI_PCI_LINK_FILE_STATUS "state"
55 #define ACPI_PCI_LINK_MAX_POSSIBLE 16
57 static int acpi_pci_link_add (struct acpi_device *device);
58 static int acpi_pci_link_remove (struct acpi_device *device, int type);
60 static struct acpi_driver acpi_pci_link_driver = {
61 .name = ACPI_PCI_LINK_DRIVER_NAME,
62 .class = ACPI_PCI_LINK_CLASS,
63 .ids = ACPI_PCI_LINK_HID,
64 .ops = {
65 .add = acpi_pci_link_add,
66 .remove = acpi_pci_link_remove,
70 struct acpi_pci_link_irq {
71 u8 active; /* Current IRQ */
72 u8 possible_count;
73 u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
76 struct acpi_pci_link {
77 struct list_head node;
78 struct acpi_device *device;
79 acpi_handle handle;
80 struct acpi_pci_link_irq irq;
83 static struct {
84 int count;
85 struct list_head entries;
86 } acpi_link;
89 /* --------------------------------------------------------------------------
90 PCI Link Device Management
91 -------------------------------------------------------------------------- */
93 static acpi_status
94 acpi_pci_link_check_possible (
95 struct acpi_resource *resource,
96 void *context)
98 struct acpi_pci_link *link = (struct acpi_pci_link *) context;
99 int i = 0;
101 ACPI_FUNCTION_TRACE("acpi_pci_link_check_possible");
103 switch (resource->id) {
104 case ACPI_RSTYPE_START_DPF:
105 return AE_OK;
106 case ACPI_RSTYPE_IRQ:
108 struct acpi_resource_irq *p = &resource->data.irq;
109 if (!p || !p->number_of_interrupts) {
110 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Blank IRQ resource\n"));
111 return AE_OK;
113 for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
114 if (!p->interrupts[i]) {
115 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ %d\n", p->interrupts[i]));
116 continue;
118 link->irq.possible[i] = p->interrupts[i];
119 link->irq.possible_count++;
121 break;
123 case ACPI_RSTYPE_EXT_IRQ:
125 struct acpi_resource_ext_irq *p = &resource->data.extended_irq;
126 if (!p || !p->number_of_interrupts) {
127 ACPI_DEBUG_PRINT((ACPI_DB_WARN,
128 "Blank IRQ resource\n"));
129 return AE_OK;
131 for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
132 if (!p->interrupts[i]) {
133 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ %d\n", p->interrupts[i]));
134 continue;
136 link->irq.possible[i] = p->interrupts[i];
137 link->irq.possible_count++;
139 break;
141 default:
142 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
143 "Resource is not an IRQ entry\n"));
144 return AE_OK;
147 return AE_CTRL_TERMINATE;
151 static int
152 acpi_pci_link_get_possible (
153 struct acpi_pci_link *link)
155 acpi_status status;
157 ACPI_FUNCTION_TRACE("acpi_pci_link_get_possible");
159 if (!link)
160 return_VALUE(-EINVAL);
162 status = acpi_walk_resources(link->handle, METHOD_NAME__PRS,
163 acpi_pci_link_check_possible, link);
164 if (ACPI_FAILURE(status)) {
165 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRS\n"));
166 return_VALUE(-ENODEV);
169 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
170 "Found %d possible IRQs\n", link->irq.possible_count));
172 return_VALUE(0);
176 static acpi_status
177 acpi_pci_link_check_current (
178 struct acpi_resource *resource,
179 void *context)
181 int *irq = (int *) context;
183 ACPI_FUNCTION_TRACE("acpi_pci_link_check_current");
185 switch (resource->id) {
186 case ACPI_RSTYPE_IRQ:
188 struct acpi_resource_irq *p = &resource->data.irq;
189 if (!p || !p->number_of_interrupts) {
190 ACPI_DEBUG_PRINT((ACPI_DB_WARN,
191 "Blank IRQ resource\n"));
192 return AE_OK;
194 *irq = p->interrupts[0];
195 break;
197 case ACPI_RSTYPE_EXT_IRQ:
199 struct acpi_resource_ext_irq *p = &resource->data.extended_irq;
200 if (!p || !p->number_of_interrupts) {
201 ACPI_DEBUG_PRINT((ACPI_DB_WARN,
202 "Blank IRQ resource\n"));
203 return AE_OK;
205 *irq = p->interrupts[0];
206 break;
208 default:
209 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
210 "Resource isn't an IRQ\n"));
211 return AE_OK;
213 return AE_CTRL_TERMINATE;
217 static int
218 acpi_pci_link_get_current (
219 struct acpi_pci_link *link)
221 int result = 0;
222 acpi_status status = AE_OK;
223 int irq = 0;
225 ACPI_FUNCTION_TRACE("acpi_pci_link_get_current");
227 if (!link || !link->handle)
228 return_VALUE(-EINVAL);
230 link->irq.active = 0;
232 /* Make sure the link is enabled (no use querying if it isn't). */
233 result = acpi_bus_get_status(link->device);
234 if (result) {
235 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
236 goto end;
238 if (!link->device->status.enabled) {
239 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link disabled\n"));
240 return_VALUE(0);
244 * Query and parse _CRS to get the current IRQ assignment.
247 status = acpi_walk_resources(link->handle, METHOD_NAME__CRS,
248 acpi_pci_link_check_current, &irq);
249 if (ACPI_FAILURE(status)) {
250 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _CRS\n"));
251 result = -ENODEV;
252 goto end;
255 if (!irq) {
256 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No IRQ resource found\n"));
257 result = -ENODEV;
258 goto end;
262 * Note that we don't validate that the current IRQ (_CRS) exists
263 * within the possible IRQs (_PRS): we blindly assume that whatever
264 * IRQ a boot-enabled Link device is set to is the correct one.
265 * (Required to support systems such as the Toshiba 5005-S504.)
268 link->irq.active = irq;
270 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active));
272 end:
273 return_VALUE(result);
277 static int
278 acpi_pci_link_set (
279 struct acpi_pci_link *link,
280 int irq)
282 int result = 0;
283 acpi_status status = AE_OK;
284 struct {
285 struct acpi_resource res;
286 struct acpi_resource end;
287 } resource;
288 struct acpi_buffer buffer = {sizeof(resource)+1, &resource};
289 int i = 0;
290 int valid = 0;
292 ACPI_FUNCTION_TRACE("acpi_pci_link_set");
294 if (!link || !irq)
295 return_VALUE(-EINVAL);
297 /* See if we're already at the target IRQ. */
298 if (irq == link->irq.active)
299 return_VALUE(0);
301 /* Make sure the target IRQ in the list of possible IRQs. */
302 for (i=0; i<link->irq.possible_count; i++) {
303 if (irq == link->irq.possible[i])
304 valid = 1;
306 if (!valid) {
307 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Target IRQ %d invalid\n", irq));
308 return_VALUE(-EINVAL);
311 memset(&resource, 0, sizeof(resource));
313 /* NOTE: PCI interrupts are always level / active_low / shared. */
314 if (irq <= 15) {
315 resource.res.id = ACPI_RSTYPE_IRQ;
316 resource.res.length = sizeof(struct acpi_resource);
317 resource.res.data.irq.edge_level = ACPI_LEVEL_SENSITIVE;
318 resource.res.data.irq.active_high_low = ACPI_ACTIVE_LOW;
319 resource.res.data.irq.shared_exclusive = ACPI_SHARED;
320 resource.res.data.irq.number_of_interrupts = 1;
321 resource.res.data.irq.interrupts[0] = irq;
323 else {
324 resource.res.id = ACPI_RSTYPE_EXT_IRQ;
325 resource.res.length = sizeof(struct acpi_resource);
326 resource.res.data.extended_irq.producer_consumer = ACPI_CONSUMER;
327 resource.res.data.extended_irq.edge_level = ACPI_LEVEL_SENSITIVE;
328 resource.res.data.extended_irq.active_high_low = ACPI_ACTIVE_LOW;
329 resource.res.data.extended_irq.shared_exclusive = ACPI_SHARED;
330 resource.res.data.extended_irq.number_of_interrupts = 1;
331 resource.res.data.extended_irq.interrupts[0] = irq;
332 /* ignore resource_source, it's optional */
334 resource.end.id = ACPI_RSTYPE_END_TAG;
336 status = acpi_set_current_resources(link->handle, &buffer);
337 if (ACPI_FAILURE(status)) {
338 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n"));
339 return_VALUE(-ENODEV);
342 /* Make sure the device is enabled. */
343 result = acpi_bus_get_status(link->device);
344 if (result) {
345 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
346 return_VALUE(result);
348 if (!link->device->status.enabled) {
349 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link disabled\n"));
350 return_VALUE(-ENODEV);
353 /* Make sure the active IRQ is the one we requested. */
354 result = acpi_pci_link_get_current(link);
355 if (result) {
356 return_VALUE(result);
358 if (link->irq.active != irq) {
359 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
360 "Attempt to enable at IRQ %d resulted in IRQ %d\n",
361 irq, link->irq.active));
362 link->irq.active = 0;
363 return_VALUE(-ENODEV);
366 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", link->irq.active));
368 return_VALUE(0);
372 /* --------------------------------------------------------------------------
373 PCI Link IRQ Management
374 -------------------------------------------------------------------------- */
376 #define ACPI_MAX_IRQS 256
377 #define ACPI_MAX_ISA_IRQ 16
380 * IRQ penalties are used to promote PCI IRQ balancing. We set each ISA-
381 * possible IRQ (0-15) with a default penalty relative to its feasibility
382 * for PCI's use:
384 * Never use: 0, 1, 2 (timer, keyboard, and cascade)
385 * Avoid using: 13, 14, and 15 (FP error and IDE)
386 * Penalize: 3, 4, 6, 7, 12 (known ISA uses)
388 * Thus we're left with IRQs 5, 9, 10, 11, and everything above 15 (IO[S]APIC)
389 * as 'best bets' for PCI use.
392 static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
393 1000000, 1000000, 1000000, 10000,
394 10000, 0, 10000, 10000,
395 10000, 0, 0, 0,
396 10000, 100000, 100000, 100000,
401 acpi_pci_link_check (void)
403 struct list_head *node = NULL;
404 struct acpi_pci_link *link = NULL;
405 int i = 0;
407 ACPI_FUNCTION_TRACE("acpi_pci_link_check");
410 * Pass #1: Update penalties to facilitate IRQ balancing.
412 list_for_each(node, &acpi_link.entries) {
414 link = list_entry(node, struct acpi_pci_link, node);
415 if (!link) {
416 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
417 continue;
420 if (link->irq.active)
421 acpi_irq_penalty[link->irq.active] += 100;
422 else if (link->irq.possible_count) {
423 int penalty = 100 / link->irq.possible_count;
424 for (i=0; i<link->irq.possible_count; i++) {
425 if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
426 acpi_irq_penalty[link->irq.possible[i]] += penalty;
432 * Pass #2: Enable boot-disabled Links at 'best' IRQ.
434 list_for_each(node, &acpi_link.entries) {
435 int irq = 0;
436 int i = 0;
438 link = list_entry(node, struct acpi_pci_link, node);
439 if (!link || !link->irq.possible_count) {
440 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
441 continue;
444 if (link->irq.active)
445 continue;
447 irq = link->irq.possible[0];
450 * Select the best IRQ. This is done in reverse to promote
451 * the use of IRQs 9, 10, 11, and >15.
453 for (i=(link->irq.possible_count-1); i>0; i--) {
454 if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
455 irq = link->irq.possible[i];
458 /* Enable the link device at this IRQ. */
459 acpi_pci_link_set(link, irq);
461 acpi_irq_penalty[link->irq.active] += 100;
463 printk(PREFIX "%s [%s] enabled at IRQ %d\n",
464 acpi_device_name(link->device),
465 acpi_device_bid(link->device), link->irq.active);
468 return_VALUE(0);
473 acpi_pci_link_get_irq (
474 acpi_handle handle,
475 int index)
477 int result = 0;
478 struct acpi_device *device = NULL;
479 struct acpi_pci_link *link = NULL;
481 ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq");
483 result = acpi_bus_get_device(handle, &device);
484 if (result) {
485 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n"));
486 return_VALUE(0);
489 link = (struct acpi_pci_link *) acpi_driver_data(device);
490 if (!link) {
491 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
492 return_VALUE(0);
495 /* TBD: Support multiple index (IRQ) entries per Link Device */
496 if (index) {
497 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid index %d\n", index));
498 return_VALUE(0);
501 if (!link->irq.active) {
502 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link disabled\n"));
503 return_VALUE(0);
506 return_VALUE(link->irq.active);
510 /* --------------------------------------------------------------------------
511 Driver Interface
512 -------------------------------------------------------------------------- */
514 static int
515 acpi_pci_link_add (
516 struct acpi_device *device)
518 int result = 0;
519 struct acpi_pci_link *link = NULL;
520 int i = 0;
521 int found = 0;
523 ACPI_FUNCTION_TRACE("acpi_pci_link_add");
525 if (!device)
526 return_VALUE(-EINVAL);
528 link = kmalloc(sizeof(struct acpi_pci_link), GFP_KERNEL);
529 if (!link)
530 return_VALUE(-ENOMEM);
531 memset(link, 0, sizeof(struct acpi_pci_link));
533 link->device = device;
534 link->handle = device->handle;
535 sprintf(acpi_device_name(device), "%s", ACPI_PCI_LINK_DEVICE_NAME);
536 sprintf(acpi_device_class(device), "%s", ACPI_PCI_LINK_CLASS);
537 acpi_driver_data(device) = link;
539 result = acpi_pci_link_get_possible(link);
540 if (result)
541 goto end;
543 acpi_pci_link_get_current(link);
545 printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device), acpi_device_bid(device));
546 for (i = 0; i < link->irq.possible_count; i++) {
547 if (link->irq.active == link->irq.possible[i]) {
548 printk(" *%d", link->irq.possible[i]);
549 found = 1;
551 else
552 printk(" %d", link->irq.possible[i]);
554 if (!link->irq.active)
555 printk(", disabled");
556 else if (!found)
557 printk(", enabled at IRQ %d", link->irq.active);
558 printk(")\n");
560 /* TBD: Acquire/release lock */
561 list_add_tail(&link->node, &acpi_link.entries);
562 acpi_link.count++;
564 end:
565 if (result)
566 kfree(link);
568 return_VALUE(result);
572 static int
573 acpi_pci_link_remove (
574 struct acpi_device *device,
575 int type)
577 struct acpi_pci_link *link = NULL;
579 ACPI_FUNCTION_TRACE("acpi_pci_link_remove");
581 if (!device || !acpi_driver_data(device))
582 return_VALUE(-EINVAL);
584 link = (struct acpi_pci_link *) acpi_driver_data(device);
586 /* TBD: Acquire/release lock */
587 list_del(&link->node);
589 kfree(link);
591 return_VALUE(0);
595 static int __init acpi_pci_link_init (void)
597 ACPI_FUNCTION_TRACE("acpi_pci_link_init");
599 if (acpi_disabled)
600 return_VALUE(0);
602 acpi_link.count = 0;
603 INIT_LIST_HEAD(&acpi_link.entries);
605 if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0)
606 return_VALUE(-ENODEV);
608 return_VALUE(0);
611 subsys_initcall(acpi_pci_link_init);