]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/acpi/pci_link.c
[ACPI] update /proc/acpi/processor/*/power even if only C1 support
[net-next-2.6.git] / drivers / acpi / pci_link.c
CommitLineData
1da177e4
LT
1/*
2 * pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 34 $)
3 *
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>
7 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 *
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.
14 *
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.
19 *
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.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 *
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).
30 */
31
32#include <linux/sysdev.h>
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/types.h>
37#include <linux/proc_fs.h>
38#include <linux/spinlock.h>
39#include <linux/pm.h>
40#include <linux/pci.h>
41
42#include <acpi/acpi_bus.h>
43#include <acpi/acpi_drivers.h>
44
45
46#define _COMPONENT ACPI_PCI_COMPONENT
47ACPI_MODULE_NAME ("pci_link")
48
49#define ACPI_PCI_LINK_CLASS "pci_irq_routing"
50#define ACPI_PCI_LINK_HID "PNP0C0F"
51#define ACPI_PCI_LINK_DRIVER_NAME "ACPI PCI Interrupt Link Driver"
52#define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link"
53#define ACPI_PCI_LINK_FILE_INFO "info"
54#define ACPI_PCI_LINK_FILE_STATUS "state"
55
56#define ACPI_PCI_LINK_MAX_POSSIBLE 16
57
58static int acpi_pci_link_add (struct acpi_device *device);
59static int acpi_pci_link_remove (struct acpi_device *device, int type);
60
61static struct acpi_driver acpi_pci_link_driver = {
62 .name = ACPI_PCI_LINK_DRIVER_NAME,
63 .class = ACPI_PCI_LINK_CLASS,
64 .ids = ACPI_PCI_LINK_HID,
65 .ops = {
66 .add = acpi_pci_link_add,
67 .remove = acpi_pci_link_remove,
68 },
69};
70
71struct acpi_pci_link_irq {
72 u8 active; /* Current IRQ */
73 u8 edge_level; /* All IRQs */
74 u8 active_high_low; /* All IRQs */
1da177e4
LT
75 u8 resource_type;
76 u8 possible_count;
77 u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
362b06bb
DSL
78 u8 initialized:1;
79 u8 suspend_resume:1;
80 u8 reserved:6;
1da177e4
LT
81};
82
83struct acpi_pci_link {
84 struct list_head node;
85 struct acpi_device *device;
86 acpi_handle handle;
87 struct acpi_pci_link_irq irq;
88};
89
90static struct {
91 int count;
92 struct list_head entries;
93} acpi_link;
94
95
96/* --------------------------------------------------------------------------
97 PCI Link Device Management
98 -------------------------------------------------------------------------- */
99
100/*
101 * set context (link) possible list from resource list
102 */
103static acpi_status
104acpi_pci_link_check_possible (
105 struct acpi_resource *resource,
106 void *context)
107{
108 struct acpi_pci_link *link = (struct acpi_pci_link *) context;
109 u32 i = 0;
110
111 ACPI_FUNCTION_TRACE("acpi_pci_link_check_possible");
112
113 switch (resource->id) {
114 case ACPI_RSTYPE_START_DPF:
115 return_ACPI_STATUS(AE_OK);
116 case ACPI_RSTYPE_IRQ:
117 {
118 struct acpi_resource_irq *p = &resource->data.irq;
119 if (!p || !p->number_of_interrupts) {
120 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Blank IRQ resource\n"));
121 return_ACPI_STATUS(AE_OK);
122 }
123 for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
124 if (!p->interrupts[i]) {
125 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ %d\n", p->interrupts[i]));
126 continue;
127 }
128 link->irq.possible[i] = p->interrupts[i];
129 link->irq.possible_count++;
130 }
131 link->irq.edge_level = p->edge_level;
132 link->irq.active_high_low = p->active_high_low;
133 link->irq.resource_type = ACPI_RSTYPE_IRQ;
134 break;
135 }
136 case ACPI_RSTYPE_EXT_IRQ:
137 {
138 struct acpi_resource_ext_irq *p = &resource->data.extended_irq;
139 if (!p || !p->number_of_interrupts) {
140 ACPI_DEBUG_PRINT((ACPI_DB_WARN,
141 "Blank EXT IRQ resource\n"));
142 return_ACPI_STATUS(AE_OK);
143 }
144 for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
145 if (!p->interrupts[i]) {
146 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ %d\n", p->interrupts[i]));
147 continue;
148 }
149 link->irq.possible[i] = p->interrupts[i];
150 link->irq.possible_count++;
151 }
152 link->irq.edge_level = p->edge_level;
153 link->irq.active_high_low = p->active_high_low;
154 link->irq.resource_type = ACPI_RSTYPE_EXT_IRQ;
155 break;
156 }
157 default:
158 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
159 "Resource is not an IRQ entry\n"));
160 return_ACPI_STATUS(AE_OK);
161 }
162
163 return_ACPI_STATUS(AE_CTRL_TERMINATE);
164}
165
166
167static int
168acpi_pci_link_get_possible (
169 struct acpi_pci_link *link)
170{
171 acpi_status status;
172
173 ACPI_FUNCTION_TRACE("acpi_pci_link_get_possible");
174
175 if (!link)
176 return_VALUE(-EINVAL);
177
178 status = acpi_walk_resources(link->handle, METHOD_NAME__PRS,
179 acpi_pci_link_check_possible, link);
180 if (ACPI_FAILURE(status)) {
181 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRS\n"));
182 return_VALUE(-ENODEV);
183 }
184
185 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
186 "Found %d possible IRQs\n", link->irq.possible_count));
187
188 return_VALUE(0);
189}
190
191
192static acpi_status
193acpi_pci_link_check_current (
194 struct acpi_resource *resource,
195 void *context)
196{
197 int *irq = (int *) context;
198
199 ACPI_FUNCTION_TRACE("acpi_pci_link_check_current");
200
201 switch (resource->id) {
202 case ACPI_RSTYPE_IRQ:
203 {
204 struct acpi_resource_irq *p = &resource->data.irq;
205 if (!p || !p->number_of_interrupts) {
206 /*
207 * IRQ descriptors may have no IRQ# bits set,
208 * particularly those those w/ _STA disabled
209 */
210 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
211 "Blank IRQ resource\n"));
212 return_ACPI_STATUS(AE_OK);
213 }
214 *irq = p->interrupts[0];
215 break;
216 }
217 case ACPI_RSTYPE_EXT_IRQ:
218 {
219 struct acpi_resource_ext_irq *p = &resource->data.extended_irq;
220 if (!p || !p->number_of_interrupts) {
221 /*
222 * extended IRQ descriptors must
223 * return at least 1 IRQ
224 */
225 ACPI_DEBUG_PRINT((ACPI_DB_WARN,
226 "Blank EXT IRQ resource\n"));
227 return_ACPI_STATUS(AE_OK);
228 }
229 *irq = p->interrupts[0];
230 break;
231 }
232 default:
233 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
234 "Resource isn't an IRQ\n"));
235 return_ACPI_STATUS(AE_OK);
236 }
237 return_ACPI_STATUS(AE_CTRL_TERMINATE);
238}
239
240/*
241 * Run _CRS and set link->irq.active
242 *
243 * return value:
244 * 0 - success
245 * !0 - failure
246 */
247static int
248acpi_pci_link_get_current (
249 struct acpi_pci_link *link)
250{
251 int result = 0;
252 acpi_status status = AE_OK;
253 int irq = 0;
254
255 ACPI_FUNCTION_TRACE("acpi_pci_link_get_current");
256
257 if (!link || !link->handle)
258 return_VALUE(-EINVAL);
259
260 link->irq.active = 0;
261
262 /* in practice, status disabled is meaningless, ignore it */
263 if (acpi_strict) {
264 /* Query _STA, set link->device->status */
265 result = acpi_bus_get_status(link->device);
266 if (result) {
267 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
268 goto end;
269 }
270
271 if (!link->device->status.enabled) {
272 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link disabled\n"));
273 return_VALUE(0);
274 }
275 }
276
277 /*
278 * Query and parse _CRS to get the current IRQ assignment.
279 */
280
281 status = acpi_walk_resources(link->handle, METHOD_NAME__CRS,
282 acpi_pci_link_check_current, &irq);
283 if (ACPI_FAILURE(status)) {
284 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _CRS\n"));
285 result = -ENODEV;
286 goto end;
287 }
288
289 if (acpi_strict && !irq) {
290 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "_CRS returned 0\n"));
291 result = -ENODEV;
292 }
293
294 link->irq.active = irq;
295
296 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active));
297
298end:
299 return_VALUE(result);
300}
301
302static int
303acpi_pci_link_set (
304 struct acpi_pci_link *link,
305 int irq)
306{
307 int result = 0;
308 acpi_status status = AE_OK;
309 struct {
310 struct acpi_resource res;
311 struct acpi_resource end;
312 } *resource;
313 struct acpi_buffer buffer = {0, NULL};
314
315 ACPI_FUNCTION_TRACE("acpi_pci_link_set");
316
317 if (!link || !irq)
318 return_VALUE(-EINVAL);
319
320 resource = kmalloc( sizeof(*resource)+1, GFP_KERNEL);
321 if(!resource)
322 return_VALUE(-ENOMEM);
323
324 memset(resource, 0, sizeof(*resource)+1);
325 buffer.length = sizeof(*resource) +1;
326 buffer.pointer = resource;
327
328 switch(link->irq.resource_type) {
329 case ACPI_RSTYPE_IRQ:
330 resource->res.id = ACPI_RSTYPE_IRQ;
331 resource->res.length = sizeof(struct acpi_resource);
332 resource->res.data.irq.edge_level = link->irq.edge_level;
333 resource->res.data.irq.active_high_low = link->irq.active_high_low;
334 if (link->irq.edge_level == ACPI_EDGE_SENSITIVE)
335 resource->res.data.irq.shared_exclusive = ACPI_EXCLUSIVE;
336 else
337 resource->res.data.irq.shared_exclusive = ACPI_SHARED;
338 resource->res.data.irq.number_of_interrupts = 1;
339 resource->res.data.irq.interrupts[0] = irq;
340 break;
341
342 case ACPI_RSTYPE_EXT_IRQ:
343 resource->res.id = ACPI_RSTYPE_EXT_IRQ;
344 resource->res.length = sizeof(struct acpi_resource);
345 resource->res.data.extended_irq.producer_consumer = ACPI_CONSUMER;
346 resource->res.data.extended_irq.edge_level = link->irq.edge_level;
347 resource->res.data.extended_irq.active_high_low = link->irq.active_high_low;
348 if (link->irq.edge_level == ACPI_EDGE_SENSITIVE)
349 resource->res.data.irq.shared_exclusive = ACPI_EXCLUSIVE;
350 else
351 resource->res.data.irq.shared_exclusive = ACPI_SHARED;
352 resource->res.data.extended_irq.number_of_interrupts = 1;
353 resource->res.data.extended_irq.interrupts[0] = irq;
354 /* ignore resource_source, it's optional */
355 break;
356 default:
357 printk("ACPI BUG: resource_type %d\n", link->irq.resource_type);
358 result = -EINVAL;
359 goto end;
360
361 }
362 resource->end.id = ACPI_RSTYPE_END_TAG;
363
364 /* Attempt to set the resource */
365 status = acpi_set_current_resources(link->handle, &buffer);
366
367 /* check for total failure */
368 if (ACPI_FAILURE(status)) {
369 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n"));
370 result = -ENODEV;
371 goto end;
372 }
373
374 /* Query _STA, set device->status */
375 result = acpi_bus_get_status(link->device);
376 if (result) {
377 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
378 goto end;
379 }
380 if (!link->device->status.enabled) {
381 printk(KERN_WARNING PREFIX
382 "%s [%s] disabled and referenced, BIOS bug.\n",
383 acpi_device_name(link->device),
384 acpi_device_bid(link->device));
385 }
386
387 /* Query _CRS, set link->irq.active */
388 result = acpi_pci_link_get_current(link);
389 if (result) {
390 goto end;
391 }
392
393 /*
394 * Is current setting not what we set?
395 * set link->irq.active
396 */
397 if (link->irq.active != irq) {
398 /*
399 * policy: when _CRS doesn't return what we just _SRS
400 * assume _SRS worked and override _CRS value.
401 */
402 printk(KERN_WARNING PREFIX
403 "%s [%s] BIOS reported IRQ %d, using IRQ %d\n",
404 acpi_device_name(link->device),
405 acpi_device_bid(link->device),
406 link->irq.active, irq);
407 link->irq.active = irq;
408 }
409
410 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", link->irq.active));
411
412end:
413 kfree(resource);
414 return_VALUE(result);
415}
416
417
418/* --------------------------------------------------------------------------
419 PCI Link IRQ Management
420 -------------------------------------------------------------------------- */
421
422/*
423 * "acpi_irq_balance" (default in APIC mode) enables ACPI to use PIC Interrupt
424 * Link Devices to move the PIRQs around to minimize sharing.
425 *
426 * "acpi_irq_nobalance" (default in PIC mode) tells ACPI not to move any PIC IRQs
427 * that the BIOS has already set to active. This is necessary because
428 * ACPI has no automatic means of knowing what ISA IRQs are used. Note that
429 * if the BIOS doesn't set a Link Device active, ACPI needs to program it
430 * even if acpi_irq_nobalance is set.
431 *
432 * A tables of penalties avoids directing PCI interrupts to well known
433 * ISA IRQs. Boot params are available to over-ride the default table:
434 *
435 * List interrupts that are free for PCI use.
436 * acpi_irq_pci=n[,m]
437 *
438 * List interrupts that should not be used for PCI:
439 * acpi_irq_isa=n[,m]
440 *
441 * Note that PCI IRQ routers have a list of possible IRQs,
442 * which may not include the IRQs this table says are available.
443 *
444 * Since this heuristic can't tell the difference between a link
445 * that no device will attach to, vs. a link which may be shared
446 * by multiple active devices -- it is not optimal.
447 *
448 * If interrupt performance is that important, get an IO-APIC system
449 * with a pin dedicated to each device. Or for that matter, an MSI
450 * enabled system.
451 */
452
453#define ACPI_MAX_IRQS 256
454#define ACPI_MAX_ISA_IRQ 16
455
456#define PIRQ_PENALTY_PCI_AVAILABLE (0)
457#define PIRQ_PENALTY_PCI_POSSIBLE (16*16)
458#define PIRQ_PENALTY_PCI_USING (16*16*16)
459#define PIRQ_PENALTY_ISA_TYPICAL (16*16*16*16)
460#define PIRQ_PENALTY_ISA_USED (16*16*16*16*16)
461#define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16)
462
463static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
464 PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */
465 PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */
466 PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */
467 PIRQ_PENALTY_ISA_TYPICAL, /* IRQ3 serial */
468 PIRQ_PENALTY_ISA_TYPICAL, /* IRQ4 serial */
469 PIRQ_PENALTY_ISA_TYPICAL, /* IRQ5 sometimes SoundBlaster */
470 PIRQ_PENALTY_ISA_TYPICAL, /* IRQ6 */
471 PIRQ_PENALTY_ISA_TYPICAL, /* IRQ7 parallel, spurious */
472 PIRQ_PENALTY_ISA_TYPICAL, /* IRQ8 rtc, sometimes */
473 PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */
474 PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */
475 PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */
476 PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */
477 PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */
478 PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */
479 PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */
480 /* >IRQ15 */
481};
482
483int __init
484acpi_irq_penalty_init(void)
485{
486 struct list_head *node = NULL;
487 struct acpi_pci_link *link = NULL;
488 int i = 0;
489
490 ACPI_FUNCTION_TRACE("acpi_irq_penalty_init");
491
492 /*
493 * Update penalties to facilitate IRQ balancing.
494 */
495 list_for_each(node, &acpi_link.entries) {
496
497 link = list_entry(node, struct acpi_pci_link, node);
498 if (!link) {
499 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
500 continue;
501 }
502
503 /*
504 * reflect the possible and active irqs in the penalty table --
505 * useful for breaking ties.
506 */
507 if (link->irq.possible_count) {
508 int penalty = PIRQ_PENALTY_PCI_POSSIBLE / link->irq.possible_count;
509
510 for (i = 0; i < link->irq.possible_count; i++) {
511 if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
512 acpi_irq_penalty[link->irq.possible[i]] += penalty;
513 }
514
515 } else if (link->irq.active) {
516 acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_POSSIBLE;
517 }
518 }
519 /* Add a penalty for the SCI */
520 acpi_irq_penalty[acpi_fadt.sci_int] += PIRQ_PENALTY_PCI_USING;
521
522 return_VALUE(0);
523}
524
525static int acpi_irq_balance; /* 0: static, 1: balance */
526
527static int acpi_pci_link_allocate(
528 struct acpi_pci_link *link)
529{
530 int irq;
531 int i;
532
533 ACPI_FUNCTION_TRACE("acpi_pci_link_allocate");
534
362b06bb
DSL
535 if (link->irq.suspend_resume) {
536 acpi_pci_link_set(link, link->irq.active);
537 link->irq.suspend_resume = 0;
538 }
1da177e4
LT
539 if (link->irq.initialized)
540 return_VALUE(0);
541
542 /*
543 * search for active IRQ in list of possible IRQs.
544 */
545 for (i = 0; i < link->irq.possible_count; ++i) {
546 if (link->irq.active == link->irq.possible[i])
547 break;
548 }
549 /*
550 * forget active IRQ that is not in possible list
551 */
552 if (i == link->irq.possible_count) {
553 if (acpi_strict)
554 printk(KERN_WARNING PREFIX "_CRS %d not found"
555 " in _PRS\n", link->irq.active);
556 link->irq.active = 0;
557 }
558
559 /*
560 * if active found, use it; else pick entry from end of possible list.
561 */
562 if (link->irq.active) {
563 irq = link->irq.active;
564 } else {
565 irq = link->irq.possible[link->irq.possible_count - 1];
566 }
567
568 if (acpi_irq_balance || !link->irq.active) {
569 /*
570 * Select the best IRQ. This is done in reverse to promote
571 * the use of IRQs 9, 10, 11, and >15.
572 */
573 for (i = (link->irq.possible_count - 1); i >= 0; i--) {
574 if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
575 irq = link->irq.possible[i];
576 }
577 }
578
579 /* Attempt to enable the link device at this IRQ. */
580 if (acpi_pci_link_set(link, irq)) {
581 printk(PREFIX "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS).\n"
582 "Try pci=noacpi or acpi=off\n",
583 acpi_device_name(link->device),
584 acpi_device_bid(link->device));
585 return_VALUE(-ENODEV);
586 } else {
587 acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
588 printk(PREFIX "%s [%s] enabled at IRQ %d\n",
589 acpi_device_name(link->device),
590 acpi_device_bid(link->device), link->irq.active);
591 }
592
593 link->irq.initialized = 1;
594
595 return_VALUE(0);
596}
597
598/*
599 * acpi_pci_link_get_irq
600 * success: return IRQ >= 0
601 * failure: return -1
602 */
603
604int
605acpi_pci_link_get_irq (
606 acpi_handle handle,
607 int index,
608 int *edge_level,
609 int *active_high_low,
610 char **name)
611{
612 int result = 0;
613 struct acpi_device *device = NULL;
614 struct acpi_pci_link *link = NULL;
615
616 ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq");
617
618 result = acpi_bus_get_device(handle, &device);
619 if (result) {
620 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n"));
621 return_VALUE(-1);
622 }
623
624 link = (struct acpi_pci_link *) acpi_driver_data(device);
625 if (!link) {
626 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
627 return_VALUE(-1);
628 }
629
630 /* TBD: Support multiple index (IRQ) entries per Link Device */
631 if (index) {
632 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid index %d\n", index));
633 return_VALUE(-1);
634 }
635
636 if (acpi_pci_link_allocate(link))
637 return_VALUE(-1);
638
639 if (!link->irq.active) {
640 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n"));
641 return_VALUE(-1);
642 }
643
644 if (edge_level) *edge_level = link->irq.edge_level;
645 if (active_high_low) *active_high_low = link->irq.active_high_low;
646 if (name) *name = acpi_device_bid(link->device);
647 return_VALUE(link->irq.active);
648}
649
650
651/* --------------------------------------------------------------------------
652 Driver Interface
653 -------------------------------------------------------------------------- */
654
655static int
656acpi_pci_link_add (
657 struct acpi_device *device)
658{
659 int result = 0;
660 struct acpi_pci_link *link = NULL;
661 int i = 0;
662 int found = 0;
663
664 ACPI_FUNCTION_TRACE("acpi_pci_link_add");
665
666 if (!device)
667 return_VALUE(-EINVAL);
668
669 link = kmalloc(sizeof(struct acpi_pci_link), GFP_KERNEL);
670 if (!link)
671 return_VALUE(-ENOMEM);
672 memset(link, 0, sizeof(struct acpi_pci_link));
673
674 link->device = device;
675 link->handle = device->handle;
676 strcpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME);
677 strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
678 acpi_driver_data(device) = link;
679
680 result = acpi_pci_link_get_possible(link);
681 if (result)
682 goto end;
683
684 /* query and set link->irq.active */
685 acpi_pci_link_get_current(link);
686
687 printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device),
688 acpi_device_bid(device));
689 for (i = 0; i < link->irq.possible_count; i++) {
690 if (link->irq.active == link->irq.possible[i]) {
691 printk(" *%d", link->irq.possible[i]);
692 found = 1;
693 }
694 else
695 printk(" %d", link->irq.possible[i]);
696 }
697
698 printk(")");
699
700 if (!found)
701 printk(" *%d", link->irq.active);
702
703 if(!link->device->status.enabled)
704 printk(", disabled.");
705
706 printk("\n");
707
708 /* TBD: Acquire/release lock */
709 list_add_tail(&link->node, &acpi_link.entries);
710 acpi_link.count++;
711
712end:
713 /* disable all links -- to be activated on use */
714 acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
715
716 if (result)
717 kfree(link);
718
719 return_VALUE(result);
720}
721
1da177e4 722static int
362b06bb
DSL
723irqrouter_suspend(
724 struct sys_device *dev,
725 u32 state)
1da177e4
LT
726{
727 struct list_head *node = NULL;
728 struct acpi_pci_link *link = NULL;
729
362b06bb 730 ACPI_FUNCTION_TRACE("irqrouter_suspend");
1da177e4
LT
731
732 list_for_each(node, &acpi_link.entries) {
1da177e4
LT
733 link = list_entry(node, struct acpi_pci_link, node);
734 if (!link) {
735 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
736 continue;
737 }
362b06bb
DSL
738 if (link->irq.active && link->irq.initialized)
739 link->irq.suspend_resume = 1;
1da177e4
LT
740 }
741 return_VALUE(0);
742}
743
744
745static int
746acpi_pci_link_remove (
747 struct acpi_device *device,
748 int type)
749{
750 struct acpi_pci_link *link = NULL;
751
752 ACPI_FUNCTION_TRACE("acpi_pci_link_remove");
753
754 if (!device || !acpi_driver_data(device))
755 return_VALUE(-EINVAL);
756
757 link = (struct acpi_pci_link *) acpi_driver_data(device);
758
759 /* TBD: Acquire/release lock */
760 list_del(&link->node);
761
762 kfree(link);
763
764 return_VALUE(0);
765}
766
767/*
768 * modify acpi_irq_penalty[] from cmdline
769 */
770static int __init acpi_irq_penalty_update(char *str, int used)
771{
772 int i;
773
774 for (i = 0; i < 16; i++) {
775 int retval;
776 int irq;
777
778 retval = get_option(&str,&irq);
779
780 if (!retval)
781 break; /* no number found */
782
783 if (irq < 0)
784 continue;
785
786 if (irq >= ACPI_MAX_IRQS)
787 continue;
788
789 if (used)
790 acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
791 else
792 acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE;
793
794 if (retval != 2) /* no next number */
795 break;
796 }
797 return 1;
798}
799
800/*
801 * We'd like PNP to call this routine for the
802 * single ISA_USED value for each legacy device.
803 * But instead it calls us with each POSSIBLE setting.
804 * There is no ISA_POSSIBLE weight, so we simply use
805 * the (small) PCI_USING penalty.
806 */
807void acpi_penalize_isa_irq(int irq)
808{
809 acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
810}
811
812/*
813 * Over-ride default table to reserve additional IRQs for use by ISA
814 * e.g. acpi_irq_isa=5
815 * Useful for telling ACPI how not to interfere with your ISA sound card.
816 */
817static int __init acpi_irq_isa(char *str)
818{
819 return acpi_irq_penalty_update(str, 1);
820}
821__setup("acpi_irq_isa=", acpi_irq_isa);
822
823/*
824 * Over-ride default table to free additional IRQs for use by PCI
825 * e.g. acpi_irq_pci=7,15
826 * Used for acpi_irq_balance to free up IRQs to reduce PCI IRQ sharing.
827 */
828static int __init acpi_irq_pci(char *str)
829{
830 return acpi_irq_penalty_update(str, 0);
831}
832__setup("acpi_irq_pci=", acpi_irq_pci);
833
834static int __init acpi_irq_nobalance_set(char *str)
835{
836 acpi_irq_balance = 0;
837 return 1;
838}
839__setup("acpi_irq_nobalance", acpi_irq_nobalance_set);
840
841int __init acpi_irq_balance_set(char *str)
842{
843 acpi_irq_balance = 1;
844 return 1;
845}
846__setup("acpi_irq_balance", acpi_irq_balance_set);
847
848
849static struct sysdev_class irqrouter_sysdev_class = {
850 set_kset_name("irqrouter"),
362b06bb 851 .suspend = irqrouter_suspend,
1da177e4
LT
852};
853
854
855static struct sys_device device_irqrouter = {
856 .id = 0,
857 .cls = &irqrouter_sysdev_class,
858};
859
860
861static int __init irqrouter_init_sysfs(void)
862{
863 int error;
864
865 ACPI_FUNCTION_TRACE("irqrouter_init_sysfs");
866
867 if (acpi_disabled || acpi_noirq)
868 return_VALUE(0);
869
870 error = sysdev_class_register(&irqrouter_sysdev_class);
871 if (!error)
872 error = sysdev_register(&device_irqrouter);
873
874 return_VALUE(error);
875}
876
877device_initcall(irqrouter_init_sysfs);
878
879
880static int __init acpi_pci_link_init (void)
881{
882 ACPI_FUNCTION_TRACE("acpi_pci_link_init");
883
884 if (acpi_noirq)
885 return_VALUE(0);
886
887 acpi_link.count = 0;
888 INIT_LIST_HEAD(&acpi_link.entries);
889
890 if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0)
891 return_VALUE(-ENODEV);
892
893 return_VALUE(0);
894}
895
896subsys_initcall(acpi_pci_link_init);