2 From: Andrew de Quincey <adq_dvb@lidskialf.net>
4 Hi, this is my next round of ACPI IRQ fixes. Attached are patches for
5 linux-2.4.23-pre3 and linux-2.6.0-test4.
7 Please CC me on any replies. I seem to be having issues with
8 vger.kernel.org right now.
10 This patch addresses the following issues:
12 1) ACPI now drops back to PIC mode if configuration in APIC mode fails.
14 2) Removed 2 lines of erroneous code in mpparse.c which causes
15 IO-APICs to be misconfigured.
17 3) ACPI now supports PIC controllers properly.
19 4) This patch includes a patch by "Jun Nakajima"
20 <jun.nakajima@intel.com> which fixes ACPI IRQ routing for all VIA
21 motherboards I have had tested so far. I've included it in this
22 patch as it changes one of the same files.
24 5) Now retries with an extended IRQ descriptor if programming a link
25 device with a "standard" IRQ descriptor fails.
27 This has already been tested successfully by multiple people.
31 arch/i386/kernel/acpi/Makefile | 2
32 arch/i386/kernel/acpi/pic.c | 102 ++++++++++++++++++
33 arch/i386/kernel/mpparse.c | 27 ++++
34 arch/ia64/kernel/iosapic.c | 19 +++
35 arch/x86_64/kernel/acpi/Makefile | 2
36 arch/x86_64/kernel/acpi/pic.c | 102 ++++++++++++++++++
37 arch/x86_64/kernel/mpparse.c | 22 +++
38 drivers/acpi/bus.c | 2
39 drivers/acpi/pci_irq.c | 218 +++++++++++++++++++++++++++++----------
40 drivers/acpi/pci_link.c | 89 ++++++++++++---
41 include/acpi/acpi_bus.h | 2
42 include/acpi/acpi_drivers.h | 8 +
43 include/asm-i386/acpi.h | 3
44 include/asm-i386/mpspec.h | 2
45 include/asm-ia64/acpi.h | 3
46 include/asm-ia64/iosapic.h | 2
47 include/asm-x86_64/acpi.h | 3
48 include/asm-x86_64/mpspec.h | 2
49 include/linux/acpi.h | 2
50 19 files changed, 522 insertions(+), 90 deletions(-)
52 diff -puN arch/i386/kernel/acpi/Makefile~acpi-irq-fixes arch/i386/kernel/acpi/Makefile
53 --- 25/arch/i386/kernel/acpi/Makefile~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
54 +++ 25-akpm/arch/i386/kernel/acpi/Makefile 2003-09-06 19:47:12.000000000 -0700
56 -obj-$(CONFIG_ACPI_BOOT) := boot.o
57 +obj-$(CONFIG_ACPI_BOOT) := boot.o pic.o
58 obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o
60 diff -puN /dev/null arch/i386/kernel/acpi/pic.c
61 --- /dev/null 2002-08-30 16:31:37.000000000 -0700
62 +++ 25-akpm/arch/i386/kernel/acpi/pic.c 2003-09-06 19:47:12.000000000 -0700
64 +/* ----------------------------------------------------------------------- *
66 + * Copyright 2003 Andrew de Quincey - All Rights Reserved
68 + * This program is free software; you can redistribute it and/or modify
69 + * it under the terms of the GNU General Public License as published by
70 + * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
71 + * USA; either version 2 of the License, or (at your option) any later
72 + * version; incorporated herein by reference.
74 + * ----------------------------------------------------------------------- */
76 +#include <linux/mm.h>
77 +#include <linux/irq.h>
78 +#include <linux/init.h>
79 +#include <linux/acpi.h>
80 +#include <linux/delay.h>
81 +#include <linux/config.h>
82 +#include <linux/bootmem.h>
83 +#include <linux/smp_lock.h>
84 +#include <linux/kernel_stat.h>
86 +#include <asm/acpi.h>
88 +#ifdef CONFIG_ACPI_PCI
90 +extern void eisa_set_level_irq(unsigned int irq);
92 +int __init pic_parse_prt (void)
94 + struct list_head *node = NULL;
95 + struct acpi_prt_entry *entry = NULL;
96 + struct acpi_prt_list *prt_list = NULL;
98 + int active_high_low = 0;
100 + int programmed[16];
102 + /* Get the current PRT */
103 + prt_list = acpi_pci_get_prt_list();
105 + if (!prt_list->count) {
106 + acpi_pci_destroy_prt_list(prt_list);
107 + printk(KERN_WARNING PREFIX "ACPI tables contain no PIC PCI IRQ "
108 + "routing entries\n");
109 + return_VALUE(-ENODEV);
112 + /* mark all IRQs as unprogrammed */
113 + memset(programmed, 0, sizeof(programmed));
116 + * Parsing through the PCI Interrupt Routing Table (PRT) and program
117 + * IRQs if necessary.
119 + list_for_each(node, &prt_list->entries) {
120 + entry = list_entry(node, struct acpi_prt_entry, node);
122 + /* Need to get irq for dynamic entry */
123 + if (entry->link.handle) {
124 + irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
126 + acpi_pci_destroy_prt_list(prt_list);
133 + /* sanity check + update entry */
134 + if ((irq < 0) || (irq > 15)) {
135 + printk(KERN_ERR "Invalid IRQ (%i) passed to PIC programming code\n", irq);
141 + /* check if it has already been dealt with */
142 + if (programmed[irq]) {
143 + printk(KERN_DEBUG "PIC: IRQ (%i) already programmed\n", irq);
146 + programmed[irq] = 1;
150 + eisa_set_level_irq(irq);
153 + printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> IRQ %d Mode %d Trigger %d\n",
154 + entry->id.segment, entry->id.bus,
155 + entry->id.device, ('A' + entry->pin),
156 + entry->irq, edge_level, active_high_low);
159 + /* if we get here, the PRT was fine. commit it */
160 + acpi_pci_commit_prt_list(prt_list);
165 +#endif /*CONFIG_ACPI_PCI*/
166 diff -puN arch/i386/kernel/mpparse.c~acpi-irq-fixes arch/i386/kernel/mpparse.c
167 --- 25/arch/i386/kernel/mpparse.c~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
168 +++ 25-akpm/arch/i386/kernel/mpparse.c 2003-09-06 19:47:12.000000000 -0700
169 @@ -1073,10 +1073,11 @@ void __init mp_config_ioapic_for_sci(int
171 #ifdef CONFIG_ACPI_PCI
173 -void __init mp_parse_prt (void)
174 +int __init mp_parse_prt (void)
176 struct list_head *node = NULL;
177 struct acpi_prt_entry *entry = NULL;
178 + struct acpi_prt_list *prt_list = NULL;
182 @@ -1084,16 +1085,31 @@ void __init mp_parse_prt (void)
184 int active_high_low = 0;
186 + /* Get the current PRT */
187 + prt_list = acpi_pci_get_prt_list();
189 + if (!prt_list->count) {
190 + acpi_pci_destroy_prt_list(prt_list);
191 + printk(KERN_WARNING PREFIX "ACPI tables contain no IO-APIC PCI IRQ "
192 + "routing entries\n");
193 + return_VALUE(-ENODEV);
197 * Parsing through the PCI Interrupt Routing Table (PRT) and program
198 * routing for all entries.
200 - list_for_each(node, &acpi_prt.entries) {
201 + list_for_each(node, &prt_list->entries) {
202 entry = list_entry(node, struct acpi_prt_entry, node);
204 /* Need to get irq for dynamic entry */
205 if (entry->link.handle) {
206 irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
208 + acpi_pci_destroy_prt_list(prt_list);
215 @@ -1113,8 +1129,6 @@ void __init mp_parse_prt (void)
217 ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start;
219 - if (!ioapic && (irq < 16))
222 * Avoid pin reprogramming. PRTs typically include entries
223 * with redundant pin->irq mappings (but unique PCI devices);
224 @@ -1146,6 +1160,11 @@ void __init mp_parse_prt (void)
225 mp_ioapic_routing[ioapic].apic_id, ioapic_pin,
229 + /* if we get here, the PRT was fine. commit it */
230 + acpi_pci_commit_prt_list(prt_list);
235 #endif /*CONFIG_ACPI_PCI*/
236 diff -puN arch/ia64/kernel/iosapic.c~acpi-irq-fixes arch/ia64/kernel/iosapic.c
237 --- 25/arch/ia64/kernel/iosapic.c~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
238 +++ 25-akpm/arch/ia64/kernel/iosapic.c 2003-09-06 19:47:12.000000000 -0700
239 @@ -680,7 +680,7 @@ iosapic_enable_intr (unsigned int vector
241 #ifdef CONFIG_ACPI_PCI
245 iosapic_parse_prt (void)
247 struct acpi_prt_entry *entry;
248 @@ -690,8 +690,19 @@ iosapic_parse_prt (void)
250 struct hw_interrupt_type *irq_type = &irq_type_iosapic_level;
252 + struct acpi_prt_list *prt_list = NULL;
254 - list_for_each(node, &acpi_prt.entries) {
255 + /* Get the current PRT */
256 + prt_list = acpi_pci_get_prt_list();
258 + if (!prt_list->count) {
259 + acpi_pci_destroy_prt_list(prt_list);
260 + printk(KERN_WARNING PREFIX "ACPI tables contain no IO-APIC PCI IRQ "
261 + "routing entries\n");
262 + return_VALUE(-ENODEV);
265 + list_for_each(node, &prt_list->entries) {
266 entry = list_entry(node, struct acpi_prt_entry, node);
268 /* We're only interested in static (non-link) entries. */
269 @@ -729,6 +740,10 @@ iosapic_parse_prt (void)
274 + /* if we get here, the PRT was fine. commit it */
275 + acpi_pci_commit_prt_list(prt_list);
279 #endif /* CONFIG_ACPI */
280 diff -puN arch/x86_64/kernel/acpi/Makefile~acpi-irq-fixes arch/x86_64/kernel/acpi/Makefile
281 --- 25/arch/x86_64/kernel/acpi/Makefile~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
282 +++ 25-akpm/arch/x86_64/kernel/acpi/Makefile 2003-09-06 19:47:12.000000000 -0700
284 -obj-$(CONFIG_ACPI_BOOT) := boot.o
285 +obj-$(CONFIG_ACPI_BOOT) := boot.o pic.o
286 obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o
288 diff -puN /dev/null arch/x86_64/kernel/acpi/pic.c
289 --- /dev/null 2002-08-30 16:31:37.000000000 -0700
290 +++ 25-akpm/arch/x86_64/kernel/acpi/pic.c 2003-09-06 19:47:12.000000000 -0700
292 +/* ----------------------------------------------------------------------- *
294 + * Copyright 2003 Andrew de Quincey - All Rights Reserved
296 + * This program is free software; you can redistribute it and/or modify
297 + * it under the terms of the GNU General Public License as published by
298 + * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
299 + * USA; either version 2 of the License, or (at your option) any later
300 + * version; incorporated herein by reference.
302 + * ----------------------------------------------------------------------- */
304 +#include <linux/mm.h>
305 +#include <linux/irq.h>
306 +#include <linux/init.h>
307 +#include <linux/acpi.h>
308 +#include <linux/delay.h>
309 +#include <linux/config.h>
310 +#include <linux/bootmem.h>
311 +#include <linux/smp_lock.h>
312 +#include <linux/kernel_stat.h>
314 +#include <asm/acpi.h>
316 +#ifdef CONFIG_ACPI_PCI
318 +extern void eisa_set_level_irq(unsigned int irq);
320 +int __init pic_parse_prt (void)
322 + struct list_head *node = NULL;
323 + struct acpi_prt_entry *entry = NULL;
324 + struct acpi_prt_list *prt_list = NULL;
325 + int edge_level = 0;
326 + int active_high_low = 0;
328 + int programmed[16];
330 + /* Get the current PRT */
331 + prt_list = acpi_pci_get_prt_list();
333 + if (!prt_list->count) {
334 + acpi_pci_destroy_prt_list(prt_list);
335 + printk(KERN_WARNING PREFIX "ACPI tables contain no PIC PCI IRQ "
336 + "routing entries\n");
337 + return_VALUE(-ENODEV);
340 + /* mark all IRQs as unprogrammed */
341 + memset(programmed, 0, sizeof(programmed));
344 + * Parsing through the PCI Interrupt Routing Table (PRT) and program
345 + * IRQs if necessary.
347 + list_for_each(node, &prt_list->entries) {
348 + entry = list_entry(node, struct acpi_prt_entry, node);
350 + /* Need to get irq for dynamic entry */
351 + if (entry->link.handle) {
352 + irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
354 + acpi_pci_destroy_prt_list(prt_list);
361 + /* sanity check + update entry */
362 + if ((irq < 0) || (irq > 15)) {
363 + printk(KERN_ERR "Invalid IRQ (%i) passed to PIC programming code\n", irq);
369 + /* check if it has already been dealt with */
370 + if (programmed[irq]) {
371 + printk(KERN_DEBUG "PIC: IRQ (%i) already programmed\n", irq);
374 + programmed[irq] = 1;
378 + eisa_set_level_irq(irq);
381 + printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> IRQ %d Mode %d Trigger %d\n",
382 + entry->id.segment, entry->id.bus,
383 + entry->id.device, ('A' + entry->pin),
384 + entry->irq, edge_level, active_high_low);
387 + /* if we get here, the PRT was fine. commit it */
388 + acpi_pci_commit_prt_list(prt_list);
393 +#endif /*CONFIG_ACPI_PCI*/
394 diff -puN arch/x86_64/kernel/mpparse.c~acpi-irq-fixes arch/x86_64/kernel/mpparse.c
395 --- 25/arch/x86_64/kernel/mpparse.c~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
396 +++ 25-akpm/arch/x86_64/kernel/mpparse.c 2003-09-06 19:47:12.000000000 -0700
397 @@ -889,16 +889,31 @@ void __init mp_parse_prt (void)
399 int active_high_low = 0;
401 + /* Get the current PRT */
402 + prt_list = acpi_pci_get_prt_list();
404 + if (!prt_list->count) {
405 + acpi_pci_destroy_prt_list(prt_list);
406 + printk(KERN_WARNING PREFIX "ACPI tables contain no IO-APIC PCI IRQ "
407 + "routing entries\n");
408 + return_VALUE(-ENODEV);
412 * Parsing through the PCI Interrupt Routing Table (PRT) and program
413 * routing for all static (IOAPIC-direct) entries.
415 - list_for_each(node, &acpi_prt.entries) {
416 + list_for_each(node, &acpi_prt->entries) {
417 entry = list_entry(node, struct acpi_prt_entry, node);
419 /* Need to get irq for dynamic entry */
420 if (entry->link.handle) {
421 irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
423 + acpi_pci_destroy_prt_list(prt_list);
430 @@ -949,8 +964,11 @@ void __init mp_parse_prt (void)
431 mp_ioapic_routing[ioapic].apic_id, ioapic_pin, vector,
435 + /* if we get here, the PRT was fine. commit it */
436 + acpi_pci_commit_prt_list(prt_list);
442 #endif /*CONFIG_ACPI_PCI*/
443 diff -puN drivers/acpi/bus.c~acpi-irq-fixes drivers/acpi/bus.c
444 --- 25/drivers/acpi/bus.c~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
445 +++ 25-akpm/drivers/acpi/bus.c 2003-09-06 19:47:12.000000000 -0700
446 @@ -536,7 +536,7 @@ acpi_bus_notify (
447 Initialization/Cleanup
448 -------------------------------------------------------------------------- */
452 acpi_bus_init_irq (void)
454 acpi_status status = AE_OK;
455 diff -puN drivers/acpi/pci_irq.c~acpi-irq-fixes drivers/acpi/pci_irq.c
456 --- 25/drivers/acpi/pci_irq.c~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
457 +++ 25-akpm/drivers/acpi/pci_irq.c 2003-09-06 19:47:12.000000000 -0700
459 #define _COMPONENT ACPI_PCI_COMPONENT
460 ACPI_MODULE_NAME ("pci_irq")
462 -struct acpi_prt_list acpi_prt;
463 +struct acpi_prt_list* acpi_prt = NULL;
465 +struct acpi_prt_ref {
466 + struct list_head node;
467 + struct acpi_device *device;
468 + acpi_handle handle;
473 +struct acpi_prt_ref_list {
475 + struct list_head entries;
478 +struct acpi_prt_ref_list acpi_prt_ref_list;
481 extern void eisa_set_level_irq(unsigned int irq);
482 @@ -71,13 +86,19 @@ acpi_pci_irq_find_prt_entry (
484 ACPI_FUNCTION_TRACE("acpi_pci_irq_find_prt_entry");
486 + /* ensure we're not called before the routing table has been determined */
487 + if (acpi_prt == NULL) {
488 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Called before acpi_prt determined"));
493 * Parse through all PRT entries looking for a match on the specified
494 * PCI device's segment, bus, device, and pin (don't care about func).
496 * TBD: Acquire/release lock
498 - list_for_each(node, &acpi_prt.entries) {
499 + list_for_each(node, &acpi_prt->entries) {
500 entry = list_entry(node, struct acpi_prt_entry, node);
501 if ((segment == entry->id.segment)
502 && (bus == entry->id.bus)
503 @@ -93,6 +114,7 @@ acpi_pci_irq_find_prt_entry (
506 acpi_pci_irq_add_entry (
507 + struct acpi_prt_list* prt_list,
511 @@ -149,12 +171,116 @@ acpi_pci_irq_add_entry (
512 ('A' + entry->pin), prt->source, entry->link.index));
514 /* TBD: Acquire/release lock */
515 - list_add_tail(&entry->node, &acpi_prt.entries);
517 + list_add_tail(&entry->node, &prt_list->entries);
524 +struct acpi_prt_list*
525 +acpi_pci_get_prt_list (void)
527 + acpi_status status = AE_OK;
528 + struct acpi_buffer buffer = {0, NULL};
529 + struct acpi_pci_routing_table *prt = NULL;
530 + struct acpi_pci_routing_table *entry = NULL;
531 + struct acpi_prt_list *prt_list = NULL;
532 + struct acpi_prt_ref *prt_ref_entry = NULL;
533 + struct list_head *node = NULL;
535 + ACPI_FUNCTION_TRACE("acpi_pci_irq_get_prt_list");
537 + /* Create a brand new acpi_prt_list */
538 + prt_list = kmalloc(sizeof(struct acpi_prt_list), GFP_KERNEL);
541 + memset(prt_list, 0, sizeof(struct acpi_prt_list));
543 + prt_list->count = 0;
544 + INIT_LIST_HEAD(&prt_list->entries);
546 + /* iterate over all entries in acpi_prt_ref_list, extracting the current _PRT entries */
547 + list_for_each(node, &acpi_prt_ref_list.entries) {
548 + prt_ref_entry = list_entry(node, struct acpi_prt_ref, node);
551 + * Evaluate this _PRT and add its entries to our local list (prt_list).
555 + buffer.pointer = NULL;
556 + status = acpi_get_irq_routing_table(prt_ref_entry->handle, &buffer);
557 + if (status != AE_BUFFER_OVERFLOW) {
558 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
559 + acpi_format_exception(status)));
564 + prt = kmalloc(buffer.length, GFP_KERNEL);
567 + return_VALUE(NULL);
569 + memset(prt, 0, buffer.length);
570 + buffer.pointer = prt;
572 + status = acpi_get_irq_routing_table(prt_ref_entry->handle, &buffer);
573 + if (ACPI_FAILURE(status)) {
574 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
575 + acpi_format_exception(status)));
576 + kfree(buffer.pointer);
583 + while (entry && (entry->length > 0)) {
584 + acpi_pci_irq_add_entry(prt_list, prt_ref_entry->handle, prt_ref_entry->segment,
585 + prt_ref_entry->bus, entry);
586 + entry = (struct acpi_pci_routing_table *)
587 + ((unsigned long) entry + entry->length);
593 + return_PTR(prt_list);
597 +acpi_pci_destroy_prt_list (struct acpi_prt_list* prt_list) {
598 + struct list_head *node = NULL;
599 + struct list_head *tmp = NULL;
600 + struct acpi_prt_entry *entry = NULL;
602 + ACPI_FUNCTION_TRACE("acpi_pci_irq_destroy_prt_list");
604 + list_for_each_safe(node, tmp, &prt_list->entries) {
605 + entry = list_entry(node, struct acpi_prt_entry, node);
615 +acpi_pci_commit_prt_list (struct acpi_prt_list* prt_list) {
617 + ACPI_FUNCTION_TRACE("acpi_pci_irq_commit_prt_list");
619 + if (acpi_prt != NULL) {
620 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Attempt to commit acpi_prt twice\n"));
621 + return_VALUE(-ENODEV);
624 + acpi_prt = prt_list;
629 acpi_pci_irq_add_prt (
630 @@ -162,21 +288,20 @@ acpi_pci_irq_add_prt (
634 - acpi_status status = AE_OK;
635 - char pathname[ACPI_PATHNAME_MAX] = {0};
636 - struct acpi_buffer buffer = {0, NULL};
637 - struct acpi_pci_routing_table *prt = NULL;
638 - struct acpi_pci_routing_table *entry = NULL;
639 - static int first_time = 1;
640 + static int first_time = 1;
641 + struct acpi_prt_ref *entry = NULL;
642 + struct acpi_buffer buffer = {0, NULL};
643 + char pathname[ACPI_PATHNAME_MAX] = {0};
645 ACPI_FUNCTION_TRACE("acpi_pci_irq_add_prt");
648 - acpi_prt.count = 0;
649 - INIT_LIST_HEAD(&acpi_prt.entries);
650 + acpi_prt_ref_list.count = 0;
651 + INIT_LIST_HEAD(&acpi_prt_ref_list.entries);
657 * NOTE: We're given a 'handle' to the _PRT object's parent device
658 * (either a PCI root bridge or PCI-PCI bridge).
659 @@ -189,42 +314,19 @@ acpi_pci_irq_add_prt (
660 printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
664 - * Evaluate this _PRT and add its entries to our global list (acpi_prt).
668 - buffer.pointer = NULL;
669 - status = acpi_get_irq_routing_table(handle, &buffer);
670 - if (status != AE_BUFFER_OVERFLOW) {
671 - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
672 - acpi_format_exception(status)));
673 - return_VALUE(-ENODEV);
676 - prt = kmalloc(buffer.length, GFP_KERNEL);
678 + entry = kmalloc(sizeof(struct acpi_prt_ref), GFP_KERNEL);
680 return_VALUE(-ENOMEM);
681 - memset(prt, 0, buffer.length);
682 - buffer.pointer = prt;
684 - status = acpi_get_irq_routing_table(handle, &buffer);
685 - if (ACPI_FAILURE(status)) {
686 - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
687 - acpi_format_exception(status)));
688 - kfree(buffer.pointer);
689 - return_VALUE(-ENODEV);
691 + memset(entry, 0, sizeof(struct acpi_prt_ref));
695 - while (entry && (entry->length > 0)) {
696 - acpi_pci_irq_add_entry(handle, segment, bus, entry);
697 - entry = (struct acpi_pci_routing_table *)
698 - ((unsigned long) entry + entry->length);
700 + entry->handle = handle;
701 + entry->segment = segment;
705 + list_add_tail(&entry->node, &acpi_prt_ref_list.entries);
706 + acpi_prt_ref_list.count++;
710 @@ -383,6 +485,14 @@ acpi_pci_irq_enable (
711 return_VALUE(dev->irq);
714 +static void __init acpi_irq_pic_mode(void)
716 + acpi_irq_model = ACPI_IRQ_MODEL_PIC;
717 + acpi_bus_init_irq();
719 + /* recalculate penalties */
720 + acpi_pci_link_calc_penalties();
724 acpi_pci_irq_init (void)
725 @@ -391,27 +501,27 @@ acpi_pci_irq_init (void)
727 ACPI_FUNCTION_TRACE("acpi_pci_irq_init");
729 - if (!acpi_prt.count) {
730 - printk(KERN_WARNING PREFIX "ACPI tables contain no PCI IRQ "
731 - "routing entries\n");
732 - return_VALUE(-ENODEV);
735 - /* Make sure all link devices have a valid IRQ. */
736 - if (acpi_pci_link_check()) {
737 - return_VALUE(-ENODEV);
739 + /* Calculate IRQ penalties for each link device */
740 + acpi_pci_link_calc_penalties();
742 #ifdef CONFIG_X86_IO_APIC
743 /* Program IOAPICs using data from PRT entries. */
744 if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
746 + if (mp_parse_prt())
747 + acpi_irq_pic_mode();
749 #ifdef CONFIG_IOSAPIC
750 if (acpi_irq_model == ACPI_IRQ_MODEL_IOSAPIC)
751 - iosapic_parse_prt();
752 + if (iosapic_parse_prt())
753 + return_VALUE(-ENODEV);
756 + /* This one is last, as a catchall */
757 + if (acpi_irq_model == ACPI_IRQ_MODEL_PIC)
758 + if (pic_parse_prt())
759 + return_VALUE(-ENODEV);
761 while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
762 acpi_pci_irq_enable(dev);
764 diff -puN drivers/acpi/pci_link.c~acpi-irq-fixes drivers/acpi/pci_link.c
765 --- 25/drivers/acpi/pci_link.c~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
766 +++ 25-akpm/drivers/acpi/pci_link.c 2003-09-06 19:47:12.000000000 -0700
767 @@ -281,6 +281,32 @@ end:
771 +acpi_pci_link_try_get_current (
772 + struct acpi_pci_link *link,
777 + ACPI_FUNCTION_TRACE("acpi_pci_link_try_get_current");
779 + result = acpi_pci_link_get_current(link);
780 + if (result && link->irq.active)
782 + return_VALUE(result);
785 + if (!link->irq.active)
787 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No active IRQ resource found\n"));
788 + printk(KERN_WARNING "_CRS returns NULL! Using IRQ %d for device (%s [%s]).\n", irq, acpi_device_name(link->device), acpi_device_bid(link->device));
789 + link->irq.active = irq;
798 struct acpi_pci_link *link,
800 @@ -294,6 +320,7 @@ acpi_pci_link_set (
801 struct acpi_buffer buffer = {sizeof(resource)+1, &resource};
804 + int resource_type = 0;
806 ACPI_FUNCTION_TRACE("acpi_pci_link_set");
808 @@ -317,20 +344,32 @@ acpi_pci_link_set (
812 + /* If IRQ<=15, first try with a "normal" IRQ descriptor. If that fails, try with
813 + * an extended one */
815 + resource_type = ACPI_RSTYPE_IRQ;
817 + resource_type = ACPI_RSTYPE_EXT_IRQ;
822 memset(&resource, 0, sizeof(resource));
824 /* NOTE: PCI interrupts are always level / active_low / shared. But not all
825 interrupts > 15 are PCI interrupts. Rely on the ACPI IRQ definition for
828 + switch(resource_type) {
829 + case ACPI_RSTYPE_IRQ:
830 resource.res.id = ACPI_RSTYPE_IRQ;
831 resource.res.length = sizeof(struct acpi_resource);
832 resource.res.data.irq.edge_level = link->irq.edge_level;
833 resource.res.data.irq.active_high_low = link->irq.active_high_low;
834 resource.res.data.irq.number_of_interrupts = 1;
835 resource.res.data.irq.interrupts[0] = irq;
840 + case ACPI_RSTYPE_EXT_IRQ:
841 resource.res.id = ACPI_RSTYPE_EXT_IRQ;
842 resource.res.length = sizeof(struct acpi_resource);
843 resource.res.data.extended_irq.producer_consumer = ACPI_CONSUMER;
844 @@ -339,11 +378,21 @@ acpi_pci_link_set (
845 resource.res.data.extended_irq.number_of_interrupts = 1;
846 resource.res.data.extended_irq.interrupts[0] = irq;
847 /* ignore resource_source, it's optional */
850 resource.end.id = ACPI_RSTYPE_END_TAG;
852 /* Attempt to set the resource */
853 status = acpi_set_current_resources(link->handle, &buffer);
855 + /* if we failed and IRQ <= 15, try again with an extended descriptor */
856 + if (ACPI_FAILURE(status) && (resource_type == ACPI_RSTYPE_IRQ)) {
857 + resource_type = ACPI_RSTYPE_EXT_IRQ;
858 + printk(PREFIX "Retrying with extended IRQ descriptor\n");
859 + goto retry_programming;
862 + /* check for total failure */
863 if (ACPI_FAILURE(status)) {
864 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n"));
865 return_VALUE(-ENODEV);
866 @@ -361,7 +410,7 @@ acpi_pci_link_set (
869 /* Make sure the active IRQ is the one we requested. */
870 - result = acpi_pci_link_get_current(link);
871 + result = acpi_pci_link_try_get_current(link, irq);
873 return_VALUE(result);
875 @@ -401,22 +450,25 @@ acpi_pci_link_set (
876 * as 'best bets' for PCI use.
879 -static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
880 +static int acpi_irq_default_penalty[ACPI_MAX_IRQS] = {
881 1000000, 1000000, 1000000, 10000,
882 10000, 0, 10000, 10000,
884 10000, 100000, 100000, 100000,
887 +static int acpi_irq_penalty[ACPI_MAX_IRQS] = { 0 };
890 -acpi_pci_link_check (void)
891 +acpi_pci_link_calc_penalties (void)
893 struct list_head *node = NULL;
894 struct acpi_pci_link *link = NULL;
897 - ACPI_FUNCTION_TRACE("acpi_pci_link_check");
898 + ACPI_FUNCTION_TRACE("acpi_pci_link_calc_penalties");
900 + memcpy(&acpi_irq_penalty, &acpi_irq_default_penalty, sizeof(acpi_irq_default_penalty));
903 * Update penalties to facilitate IRQ balancing.
904 @@ -428,6 +480,7 @@ acpi_pci_link_check (void)
905 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
908 + link->irq.setonboot = 0;
910 if (link->irq.active)
911 acpi_irq_penalty[link->irq.active] += 100;
912 @@ -458,18 +511,18 @@ static int acpi_pci_link_allocate(struct
913 irq = link->irq.possible[0];
917 - * Select the best IRQ. This is done in reverse to promote
918 - * the use of IRQs 9, 10, 11, and >15.
920 - for (i=(link->irq.possible_count-1); i>0; i--) {
921 - if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
922 - irq = link->irq.possible[i];
925 + * Select the best IRQ. This is done in reverse to promote
926 + * the use of IRQs 9, 10, 11, and >15.
928 + for (i=(link->irq.possible_count-1); i>0; i--) {
929 + if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
930 + irq = link->irq.possible[i];
933 /* Attempt to enable the link device at this IRQ. */
934 if (acpi_pci_link_set(link, irq)) {
935 - printk(PREFIX "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS). Aborting ACPI-based IRQ routing. Try pci=noacpi or acpi=off\n",
936 + printk(PREFIX "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS, please report to acpi-devel!)\n",
937 acpi_device_name(link->device),
938 acpi_device_bid(link->device));
939 return_VALUE(-ENODEV);
940 @@ -574,10 +627,6 @@ acpi_pci_link_add (
942 printk(" %d", link->irq.possible[i]);
944 - if (!link->irq.active)
945 - printk(", disabled");
947 - printk(", enabled at IRQ %d", link->irq.active);
950 /* TBD: Acquire/release lock */
951 diff -puN include/acpi/acpi_bus.h~acpi-irq-fixes include/acpi/acpi_bus.h
952 --- 25/include/acpi/acpi_bus.h~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
953 +++ 25-akpm/include/acpi/acpi_bus.h 2003-09-06 19:47:12.000000000 -0700
954 @@ -307,6 +307,8 @@ int acpi_bus_unregister_driver (struct a
955 int acpi_create_dir(struct acpi_device *);
956 void acpi_remove_dir(struct acpi_device *);
958 +int acpi_bus_init_irq (void);
960 #endif /*CONFIG_ACPI_BUS*/
962 #endif /*__ACPI_BUS_H__*/
963 diff -puN include/acpi/acpi_drivers.h~acpi-irq-fixes include/acpi/acpi_drivers.h
964 --- 25/include/acpi/acpi_drivers.h~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
965 +++ 25-akpm/include/acpi/acpi_drivers.h 2003-09-06 19:47:12.000000000 -0700
967 #ifndef __ACPI_DRIVERS_H__
968 #define __ACPI_DRIVERS_H__
970 +/* forward definitions */
971 +struct acpi_prt_list;
973 #include <linux/acpi.h>
974 #include <acpi/acpi_bus.h>
976 @@ -59,12 +62,15 @@ void acpi_pci_get_translations (struct a
978 /* ACPI PCI Interrupt Link (pci_link.c) */
980 -int acpi_pci_link_check (void);
981 +int acpi_pci_link_calc_penalties (void);
982 int acpi_pci_link_get_irq (acpi_handle handle, int index, int* edge_level, int* active_high_low);
984 /* ACPI PCI Interrupt Routing (pci_irq.c) */
986 int acpi_pci_irq_add_prt (acpi_handle handle, int segment, int bus);
987 +int acpi_pci_commit_prt_list (struct acpi_prt_list* prt_list);
988 +int acpi_pci_destroy_prt_list (struct acpi_prt_list* prt_list);
989 +struct acpi_prt_list* acpi_pci_get_prt_list (void);
991 /* ACPI PCI Device Binding (pci_bind.c) */
993 diff -puN include/asm-i386/acpi.h~acpi-irq-fixes include/asm-i386/acpi.h
994 --- 25/include/asm-i386/acpi.h~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
995 +++ 25-akpm/include/asm-i386/acpi.h 2003-09-06 19:47:12.000000000 -0700
996 @@ -151,6 +151,9 @@ extern unsigned long acpi_wakeup_address
997 /* early initialization routine */
998 extern void acpi_reserve_bootmem(void);
1000 +/* ACPI-based PIC initialisation */
1001 +extern int pic_parse_prt (void);
1003 #endif /*CONFIG_ACPI_SLEEP*/
1005 #endif /*__KERNEL__*/
1006 diff -puN include/asm-i386/mpspec.h~acpi-irq-fixes include/asm-i386/mpspec.h
1007 --- 25/include/asm-i386/mpspec.h~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
1008 +++ 25-akpm/include/asm-i386/mpspec.h 2003-09-06 19:47:12.000000000 -0700
1009 @@ -37,7 +37,7 @@ extern void mp_register_lapic_address (u
1010 extern void mp_register_ioapic (u8 id, u32 address, u32 irq_base);
1011 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 global_irq);
1012 extern void mp_config_acpi_legacy_irqs (void);
1013 -extern void mp_parse_prt (void);
1014 +extern int mp_parse_prt (void);
1016 #ifdef CONFIG_X86_IO_APIC
1017 extern void mp_config_ioapic_for_sci(int irq);
1018 diff -puN include/asm-ia64/acpi.h~acpi-irq-fixes include/asm-ia64/acpi.h
1019 --- 25/include/asm-ia64/acpi.h~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
1020 +++ 25-akpm/include/asm-ia64/acpi.h 2003-09-06 19:47:12.000000000 -0700
1021 @@ -112,6 +112,9 @@ extern int __initdata pxm_to_nid_map[MAX
1022 extern int __initdata nid_to_pxm_map[NR_NODES];
1025 +/* ia64 machines don't have PIC controllers */
1026 +static inline int pic_parse_prt(void) { return -1; }
1028 #endif /*__KERNEL__*/
1030 #endif /*_ASM_ACPI_H*/
1031 diff -puN include/asm-ia64/iosapic.h~acpi-irq-fixes include/asm-ia64/iosapic.h
1032 --- 25/include/asm-ia64/iosapic.h~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
1033 +++ 25-akpm/include/asm-ia64/iosapic.h 2003-09-06 19:47:12.000000000 -0700
1034 @@ -57,7 +57,7 @@ extern void __init iosapic_init (unsigne
1035 unsigned int gsi_base);
1036 extern int gsi_to_vector (unsigned int gsi);
1037 extern int gsi_to_irq (unsigned int gsi);
1038 -extern void __init iosapic_parse_prt (void);
1039 +extern int __init iosapic_parse_prt (void);
1040 extern void iosapic_enable_intr (unsigned int vector);
1041 extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity,
1042 unsigned long trigger);
1043 diff -puN include/asm-x86_64/acpi.h~acpi-irq-fixes include/asm-x86_64/acpi.h
1044 --- 25/include/asm-x86_64/acpi.h~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
1045 +++ 25-akpm/include/asm-x86_64/acpi.h 2003-09-06 19:47:12.000000000 -0700
1046 @@ -146,6 +146,9 @@ extern int acpi_disabled;
1047 #define BROKEN_ACPI_Sx 0x0001
1048 #define BROKEN_INIT_AFTER_S1 0x0002
1050 +/* ACPI-based PIC initialisation */
1051 +extern int pic_parse_prt (void);
1053 #endif /*__KERNEL__*/
1055 #endif /*_ASM_ACPI_H*/
1056 diff -puN include/asm-x86_64/mpspec.h~acpi-irq-fixes include/asm-x86_64/mpspec.h
1057 --- 25/include/asm-x86_64/mpspec.h~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
1058 +++ 25-akpm/include/asm-x86_64/mpspec.h 2003-09-06 19:47:12.000000000 -0700
1059 @@ -189,7 +189,7 @@ extern void mp_register_lapic_address (u
1060 extern void mp_register_ioapic (u8 id, u32 address, u32 irq_base);
1061 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 global_irq);
1062 extern void mp_config_acpi_legacy_irqs (void);
1063 -extern void mp_parse_prt (void);
1064 +extern int mp_parse_prt (void);
1065 #endif /*CONFIG_X86_IO_APIC*/
1068 diff -puN include/linux/acpi.h~acpi-irq-fixes include/linux/acpi.h
1069 --- 25/include/linux/acpi.h~acpi-irq-fixes 2003-09-06 19:47:12.000000000 -0700
1070 +++ 25-akpm/include/linux/acpi.h 2003-09-06 19:47:12.000000000 -0700
1071 @@ -399,7 +399,7 @@ struct acpi_prt_list {
1072 struct list_head entries;
1075 -extern struct acpi_prt_list acpi_prt;
1076 +extern struct acpi_prt_list* acpi_prt;
1081 --- linux-2.6.0test5-work/arch/i386/pci/acpi.c-o 2003-08-23 13:03:09.000000000 +0200
1082 +++ linux-2.6.0test5-work/arch/i386/pci/acpi.c 2003-09-09 21:01:49.000000000 +0200
1085 static int __init pci_acpi_init(void)
1087 + extern int acpi_disabled;
1088 if (pcibios_scanned)
1091 - if (!(pci_probe & PCI_NO_ACPI_ROUTING)) {
1092 + if (!(pci_probe & PCI_NO_ACPI_ROUTING) && !acpi_disabled) {
1093 if (!acpi_pci_irq_init()) {
1094 printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
1095 printk(KERN_INFO "PCI: if you experience problems, try using option 'pci=noacpi' or even 'acpi=off'\n");
1098 --- 2.6.0-test5-mm3/drivers/acpi/pci_link.c~acpi_pci_irq_fix 2003-09-22 10:00:16.000000000 -0700
1099 +++ 2.6.0-test5-mm3/drivers/acpi/pci_link.c 2003-09-22 10:10:06.000000000 -0700
1100 @@ -500,15 +500,15 @@ static int acpi_pci_link_allocate(struct
1101 irq = link->irq.active;
1103 irq = link->irq.possible[0];
1107 - * Select the best IRQ. This is done in reverse to promote
1108 - * the use of IRQs 9, 10, 11, and >15.
1110 - for (i=(link->irq.possible_count-1); i>0; i--) {
1111 - if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
1112 - irq = link->irq.possible[i];
1114 + * Select the best IRQ. This is done in reverse to promote
1115 + * the use of IRQs 9, 10, 11, and >15.
1117 + for (i=(link->irq.possible_count-1); i>0; i--) {
1118 + if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
1119 + irq = link->irq.possible[i];
1123 /* Attempt to enable the link device at this IRQ. */