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 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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>
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
,
65 .add
= acpi_pci_link_add
,
66 .remove
= acpi_pci_link_remove
,
70 struct acpi_pci_link_irq
{
71 u8 active
; /* Current IRQ */
73 u8 possible
[ACPI_PCI_LINK_MAX_POSSIBLE
];
76 struct acpi_pci_link
{
77 struct list_head node
;
78 struct acpi_device
*device
;
80 struct acpi_pci_link_irq irq
;
85 struct list_head entries
;
89 /* --------------------------------------------------------------------------
90 PCI Link Device Management
91 -------------------------------------------------------------------------- */
94 acpi_pci_link_check_possible (
95 struct acpi_resource
*resource
,
98 struct acpi_pci_link
*link
= (struct acpi_pci_link
*) context
;
101 ACPI_FUNCTION_TRACE("acpi_pci_link_check_possible");
103 switch (resource
->id
) {
104 case ACPI_RSTYPE_START_DPF
:
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"));
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
]));
118 link
->irq
.possible
[i
] = p
->interrupts
[i
];
119 link
->irq
.possible_count
++;
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"));
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
]));
136 link
->irq
.possible
[i
] = p
->interrupts
[i
];
137 link
->irq
.possible_count
++;
142 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
143 "Resource is not an IRQ entry\n"));
147 return AE_CTRL_TERMINATE
;
152 acpi_pci_link_get_possible (
153 struct acpi_pci_link
*link
)
157 ACPI_FUNCTION_TRACE("acpi_pci_link_get_possible");
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
));
177 acpi_pci_link_check_current (
178 struct acpi_resource
*resource
,
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"));
194 *irq
= p
->interrupts
[0];
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"));
205 *irq
= p
->interrupts
[0];
209 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
210 "Resource isn't an IRQ\n"));
213 return AE_CTRL_TERMINATE
;
218 acpi_pci_link_get_current (
219 struct acpi_pci_link
*link
)
222 acpi_status status
= AE_OK
;
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
);
235 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Unable to read status\n"));
238 if (!link
->device
->status
.enabled
) {
239 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Link disabled\n"));
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"));
256 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "No IRQ resource found\n"));
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
));
273 return_VALUE(result
);
279 struct acpi_pci_link
*link
,
283 acpi_status status
= AE_OK
;
285 struct acpi_resource res
;
286 struct acpi_resource end
;
288 struct acpi_buffer buffer
= {sizeof(resource
)+1, &resource
};
292 ACPI_FUNCTION_TRACE("acpi_pci_link_set");
295 return_VALUE(-EINVAL
);
297 /* See if we're already at the target IRQ. */
298 if (irq
== link
->irq
.active
)
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
])
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. */
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
;
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
);
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
);
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
));
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
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,
396 10000, 100000, 100000, 100000,
401 acpi_pci_link_check (void)
403 struct list_head
*node
= NULL
;
404 struct acpi_pci_link
*link
= NULL
;
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
);
416 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Invalid link context\n"));
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
) {
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"));
444 if (link
->irq
.active
)
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
);
473 acpi_pci_link_get_irq (
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
);
485 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Invalid link device\n"));
489 link
= (struct acpi_pci_link
*) acpi_driver_data(device
);
491 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Invalid link context\n"));
495 /* TBD: Support multiple index (IRQ) entries per Link Device */
497 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Invalid index %d\n", index
));
501 if (!link
->irq
.active
) {
502 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Link disabled\n"));
506 return_VALUE(link
->irq
.active
);
510 /* --------------------------------------------------------------------------
512 -------------------------------------------------------------------------- */
516 struct acpi_device
*device
)
519 struct acpi_pci_link
*link
= NULL
;
523 ACPI_FUNCTION_TRACE("acpi_pci_link_add");
526 return_VALUE(-EINVAL
);
528 link
= kmalloc(sizeof(struct acpi_pci_link
), GFP_KERNEL
);
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
);
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
]);
552 printk(" %d", link
->irq
.possible
[i
]);
554 if (!link
->irq
.active
)
555 printk(", disabled");
557 printk(", enabled at IRQ %d", link
->irq
.active
);
560 /* TBD: Acquire/release lock */
561 list_add_tail(&link
->node
, &acpi_link
.entries
);
568 return_VALUE(result
);
573 acpi_pci_link_remove (
574 struct acpi_device
*device
,
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
);
595 static int __init
acpi_pci_link_init (void)
597 ACPI_FUNCTION_TRACE("acpi_pci_link_init");
603 INIT_LIST_HEAD(&acpi_link
.entries
);
605 if (acpi_bus_register_driver(&acpi_pci_link_driver
) < 0)
606 return_VALUE(-ENODEV
);
611 subsys_initcall(acpi_pci_link_init
);