linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed)
@ 2003-09-05 18:58 Andrew de Quincey
  2003-09-05 21:35 ` Jeff Garzik
  0 siblings, 1 reply; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-05 18:58 UTC (permalink / raw)
  To: torvalds; +Cc: lkml, acpi-devel, linux-acpi

Hi, this is my next round of ACPI IRQ fixes. Attached are patches for linux-2.4.23-pre3 and linux-2.6.0-test4.

Please CC me on any replies. I seem to be having issues with vger.kernel.org right now.


This patch addresses the following issues:

1) ACPI now drops back to PIC mode if configuration in APIC mode fails.

2) Removed 2 lines of erroneous code in mpparse.c which causes IO-APICs to be misconfigured.

3) ACPI now supports PIC controllers properly.

4) This patch includes a patch by "Jun Nakajima" <jun.nakajima@intel.com> which fixes ACPI IRQ routing for all 
VIA motherboards I have had tested so far. I've included it in this patch as it changes one of the same files.

5) Now retries with an extended IRQ descriptor if programming a link device with a "standard" IRQ descriptor fails.

This has already been tested successfully by multiple people.


Patch for 2.4.23-pre3:


---- BEGIN linux-2.4.23-pre3-acpi-picmode-5.patch ----
--- linux-2.4.23-pre3.orig/arch/i386/kernel/mpparse.c	2003-09-05 18:55:07.000000000 +0100
+++ linux-2.4.23-pre3/arch/i386/kernel/mpparse.c	2003-09-05 18:55:42.309730848 +0100
@@ -1263,10 +1263,11 @@
 
 #ifdef CONFIG_ACPI_PCI
 
-void __init mp_parse_prt (void)
+int __init mp_parse_prt (void)
 {
 	struct list_head	*node = NULL;
 	struct acpi_prt_entry	*entry = NULL;
+ 	struct acpi_prt_list	*prt_list = NULL;
 	int			ioapic = -1;
 	int			ioapic_pin = 0;
 	int			irq = 0;
@@ -1274,16 +1275,31 @@
 	int			edge_level = 0;
 	int			active_high_low = 0;
 
+ 	/* Get the current PRT */
+ 	prt_list = acpi_pci_get_prt_list();
+   
+ 	if (!prt_list->count) {
+ 		acpi_pci_destroy_prt_list(prt_list);
+ 		printk(KERN_WARNING "ACPI tables contain no IO-APIC PCI IRQ "
+ 			"routing entries\n");
+ 		return_VALUE(-ENODEV);
+ 	}
+   
 	/*
 	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
 	 * routing for all entries.
 	 */
-	list_for_each(node, &acpi_prt.entries) {
+	list_for_each(node, &prt_list->entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
 
 		/* Need to get irq for dynamic entry */
 		if (entry->link.handle) {
 			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
+		   
 			if (!irq)
 				continue;
 		}
@@ -1334,8 +1350,11 @@
 			mp_ioapic_routing[ioapic].apic_id, ioapic_pin, 
 			entry->irq);
 	}
-	
-	return;
+   
+ 	/* if we get here, the PRT was fine. commit it */
+ 	acpi_pci_commit_prt_list(prt_list);
+
+	return 0;
 }
 
 #endif /*CONFIG_ACPI_PCI*/
--- linux-2.4.23-pre3.orig/arch/i386/kernel/pic.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-pre3/arch/i386/kernel/pic.c	2003-09-05 18:55:42.310730696 +0100
@@ -0,0 +1,102 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2003 Andrew de Quincey - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/bootmem.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/acpi.h>
+
+#ifdef CONFIG_ACPI_PCI
+
+extern void eisa_set_level_irq(unsigned int irq);
+
+int __init pic_parse_prt (void)
+{
+	struct list_head	*node = NULL;
+	struct acpi_prt_entry	*entry = NULL;
+	struct acpi_prt_list	*prt_list = NULL;
+	int			edge_level = 0;
+	int			active_high_low = 0;
+	int			irq = 0;
+	int			programmed[16];
+
+	/* Get the current PRT */
+	prt_list = acpi_pci_get_prt_list();
+   
+	if (!prt_list->count) {
+		acpi_pci_destroy_prt_list(prt_list);
+		printk(KERN_WARNING "ACPI tables contain no PIC PCI IRQ "
+			"routing entries\n");
+		return_VALUE(-ENODEV);
+	}
+
+	/* mark all IRQs as unprogrammed */
+	memset(programmed, 0, sizeof(programmed));
+   
+	/*
+	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
+	 * IRQs if necessary.
+	 */
+	list_for_each(node, &prt_list->entries) {
+		entry = list_entry(node, struct acpi_prt_entry, node);
+
+		/* Need to get irq for dynamic entry */
+		if (entry->link.handle) {
+			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
+ 			if (!irq) 
+				continue;
+		}
+	   
+		/* sanity check + update entry */
+		if ((irq < 0) || (irq > 15)) {
+			printk(KERN_ERR "Invalid IRQ (%i) passed to PIC programming code\n", irq);
+			entry->irq = 0;
+			continue;
+		}
+		entry->irq = irq;
+
+		/* check if it has already been dealt with */
+		if (programmed[irq]) {
+			printk(KERN_DEBUG "PIC: IRQ (%i) already programmed\n", irq);
+			continue;
+		}
+		programmed[irq] = 1;
+
+		/* program it */
+		if (edge_level) {
+			eisa_set_level_irq(irq);
+		}
+	   
+		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> IRQ %d Mode %d Trigger %d\n",
+			entry->id.segment, entry->id.bus, 
+			entry->id.device, ('A' + entry->pin), 
+			entry->irq, edge_level, active_high_low);
+	}
+	
+	/* if we get here, the PRT was fine. commit it */
+	acpi_pci_commit_prt_list(prt_list);
+   
+	return 0;
+}
+
+#endif /*CONFIG_ACPI_PCI*/
--- linux-2.4.23-pre3.orig/arch/i386/kernel/Makefile	2003-08-25 12:44:39.000000000 +0100
+++ linux-2.4.23-pre3/arch/i386/kernel/Makefile	2003-09-05 18:55:42.311730544 +0100
@@ -36,7 +36,7 @@
 obj-$(CONFIG_X86_CPUID)		+= cpuid.o
 obj-$(CONFIG_MICROCODE)		+= microcode.o
 obj-$(CONFIG_APM)		+= apm.o
-obj-$(CONFIG_ACPI_BOOT)		+= acpi.o
+obj-$(CONFIG_ACPI_BOOT)		+= acpi.o pic.o
 obj-$(CONFIG_ACPI_SLEEP)	+= acpi_wakeup.o
 obj-$(CONFIG_ACPI_HT_ONLY)	+= acpitable.o
 obj-$(CONFIG_SMP)		+= smp.o smpboot.o trampoline.o
--- linux-2.4.23-pre3.orig/include/asm-i386/mpspec.h	2003-08-25 12:44:43.000000000 +0100
+++ linux-2.4.23-pre3/include/asm-i386/mpspec.h	2003-09-05 18:55:42.311730544 +0100
@@ -228,7 +228,7 @@
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 global_irq);
 extern void mp_config_acpi_legacy_irqs (void);
 extern void mp_config_ioapic_for_sci(int irq);
-extern void mp_parse_prt (void);
+extern int mp_parse_prt (void);
 #else /*!CONFIG_X86_IO_APIC*/
 static inline void mp_config_ioapic_for_sci(int irq) { }
 #endif /*!CONFIG_X86_IO_APIC*/
--- linux-2.4.23-pre3.orig/include/asm-i386/acpi.h	2003-08-25 12:44:43.000000000 +0100
+++ linux-2.4.23-pre3/include/asm-i386/acpi.h	2003-09-05 18:55:42.312730392 +0100
@@ -180,6 +180,9 @@
 /* early initialization routine */
 extern void acpi_reserve_bootmem(void);
 
+/* ACPI-based PIC initialisation */
+extern int pic_parse_prt (void);
+
 #endif /*CONFIG_ACPI_SLEEP*/
 
 
--- linux-2.4.23-pre3.orig/arch/x86_64/kernel/mpparse.c	2003-09-05 18:55:07.000000000 +0100
+++ linux-2.4.23-pre3/arch/x86_64/kernel/mpparse.c	2003-09-05 18:58:21.731495056 +0100
@@ -934,6 +934,7 @@
 {
 	struct list_head	*node = NULL;
 	struct acpi_prt_entry	*entry = NULL;
+	struct acpi_prt_list    *prt_list = NULL;   
 	int			vector = 0;
 	int			ioapic = -1;
 	int			ioapic_pin = 0;
@@ -942,16 +943,29 @@
 	int			edge_level = 0;
 	int			active_high_low = 0;
 
+	/* Get the current PRT */
+	prt_list = acpi_pci_get_prt_list();
+	if (!prt_list->count) {
+		acpi_pci_destroy_prt_list(prt_list);
+		printk(KERN_WARNING "ACPI tables contain no IO-APIC PCI IRQ "
+			"routing entries\n");
+		return_VALUE(-ENODEV);
+	}
+   
 	/*
 	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
 	 * routing for all static (IOAPIC-direct) entries.
 	 */
-	list_for_each(node, &acpi_prt.entries) {
+	list_for_each(node, &prt_list->entries) 
 		entry = list_entry(node, struct acpi_prt_entry, node);
 
 		/* Need to get irq for dynamic entry */
 		if (entry->link.handle) {
 			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
 			if (!irq)
 				continue;
 		} else {
@@ -998,8 +1012,11 @@
 			mp_ioapic_routing[ioapic].apic_id, ioapic_pin, vector, 
 			entry->irq);
 	}
-	
-	return;
+   
+ 	/* if we get here, the PRT was fine. commit it */
+ 	acpi_pci_commit_prt_list(prt_list);
+   
+	return 0;
 }
 
 #endif /*CONFIG_ACPI_PCI*/
--- linux-2.4.23-pre3.orig/arch/x86_64/kernel/pic.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-pre3/arch/x86_64/kernel/pic.c	2003-09-05 18:55:42.315729936 +0100
@@ -0,0 +1,102 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2003 Andrew de Quincey - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/bootmem.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/acpi.h>
+
+#ifdef CONFIG_ACPI_PCI
+
+extern void eisa_set_level_irq(unsigned int irq);
+
+int __init pic_parse_prt (void)
+{
+	struct list_head	*node = NULL;
+	struct acpi_prt_entry	*entry = NULL;
+	struct acpi_prt_list	*prt_list = NULL;
+	int			edge_level = 0;
+	int			active_high_low = 0;
+	int			irq = 0;
+	int			programmed[16];
+
+	/* Get the current PRT */
+	prt_list = acpi_pci_get_prt_list();
+   
+	if (!prt_list->count) {
+		acpi_pci_destroy_prt_list(prt_list);
+		printk(KERN_WARNING "ACPI tables contain no PIC PCI IRQ "
+			"routing entries\n");
+		return_VALUE(-ENODEV);
+	}
+
+	/* mark all IRQs as unprogrammed */
+	memset(programmed, 0, sizeof(programmed));
+   
+	/*
+	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
+	 * IRQs if necessary.
+	 */
+	list_for_each(node, &prt_list->entries) {
+		entry = list_entry(node, struct acpi_prt_entry, node);
+
+		/* Need to get irq for dynamic entry */
+		if (entry->link.handle) {
+			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
+ 			if (!irq) 
+				continue;
+		}
+	   
+		/* sanity check + update entry */
+		if ((irq < 0) || (irq > 15)) {
+			printk(KERN_ERR "Invalid IRQ (%i) passed to PIC programming code\n", irq);
+			entry->irq = 0;
+			continue;
+		}
+		entry->irq = irq;
+
+		/* check if it has already been dealt with */
+		if (programmed[irq]) {
+			printk(KERN_DEBUG "PIC: IRQ (%i) already programmed\n", irq);
+			continue;
+		}
+		programmed[irq] = 1;
+
+		/* program it */
+		if (edge_level) {
+			eisa_set_level_irq(irq);
+		}
+	   
+		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> IRQ %d Mode %d Trigger %d\n",
+			entry->id.segment, entry->id.bus, 
+			entry->id.device, ('A' + entry->pin), 
+			entry->irq, edge_level, active_high_low);
+	}
+	
+	/* if we get here, the PRT was fine. commit it */
+	acpi_pci_commit_prt_list(prt_list);
+   
+	return 0;
+}
+
+#endif /*CONFIG_ACPI_PCI*/
--- linux-2.4.23-pre3.orig/arch/x86_64/kernel/Makefile	2003-08-25 12:44:40.000000000 +0100
+++ linux-2.4.23-pre3/arch/x86_64/kernel/Makefile	2003-09-05 18:55:42.315729936 +0100
@@ -37,7 +37,7 @@
 obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o
 obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o
 obj-$(CONFIG_MCE) += bluesmoke.o
-obj-$(CONFIG_ACPI)		+= acpi.o
+obj-$(CONFIG_ACPI)		+= acpi.o pic.o
 obj-$(CONFIG_ACPI_SLEEP)	+= acpi_wakeup.o suspend.o
  
 
--- linux-2.4.23-pre3.orig/include/asm-x86_64/acpi.h	2003-08-25 12:44:44.000000000 +0100
+++ linux-2.4.23-pre3/include/asm-x86_64/acpi.h	2003-09-05 18:55:42.316729784 +0100
@@ -142,6 +142,9 @@
 
 extern void mp_config_ioapic_for_sci(int irq);
 
+/* ACPI-based PIC initialisation */
+extern int pic_parse_prt (void);
+
 #endif /*__KERNEL__*/
 
 #endif /*_ASM_ACPI_H*/
--- linux-2.4.23-pre3.orig/include/asm-ia64/acpi.h	2003-06-13 15:51:38.000000000 +0100
+++ linux-2.4.23-pre3/include/asm-ia64/acpi.h	2003-09-05 18:55:42.316729784 +0100
@@ -109,6 +109,9 @@
 #define MAX_PXM_DOMAINS		(256)
 #endif /* CONFIG_DISCONTIGMEM */
 
+/* ia64 machines don't have PIC controllers */
+static inline int pic_parse_prt(void) { return -1; }
+
 #endif /*__KERNEL__*/
 
 #endif /*_ASM_ACPI_H*/
--- linux-2.4.23-pre3.orig/drivers/acpi/pci_irq.c	2003-08-25 12:44:41.000000000 +0100
+++ linux-2.4.23-pre3/drivers/acpi/pci_irq.c	2003-09-05 18:55:42.317729632 +0100
@@ -50,7 +50,22 @@
 
 #define PREFIX			"PCI: "
 
-struct acpi_prt_list		acpi_prt;
+struct acpi_prt_list*		acpi_prt = NULL;
+
+struct acpi_prt_ref {
+	struct list_head	node;
+	struct acpi_device	*device;
+	acpi_handle		handle;
+	int segment;
+	int bus;
+};
+
+struct acpi_prt_ref_list {
+	int			count;
+	struct list_head	entries;
+};				
+
+struct acpi_prt_ref_list acpi_prt_ref_list;
 
 #ifdef CONFIG_X86
 extern void eisa_set_level_irq(unsigned int irq);
@@ -73,13 +88,19 @@
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_find_prt_entry");
 
+	/* ensure we're not called before the routing table has been determined */
+	if (acpi_prt == NULL) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Called before acpi_prt determined"));
+		return_PTR(NULL);
+ 	}
+   
 	/*
 	 * Parse through all PRT entries looking for a match on the specified
 	 * PCI device's segment, bus, device, and pin (don't care about func).
 	 *
 	 * TBD: Acquire/release lock
 	 */
-	list_for_each(node, &acpi_prt.entries) {
+	list_for_each(node, &acpi_prt->entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
 		if ((segment == entry->id.segment) 
 			&& (bus == entry->id.bus) 
@@ -95,6 +116,7 @@
 
 static int
 acpi_pci_irq_add_entry (
+	struct acpi_prt_list*		prt_list,
 	acpi_handle			handle,
 	int				segment,
 	int				bus,
@@ -151,12 +173,115 @@
 		('A' + entry->pin), prt->source, entry->link.index));
 
 	/* TBD: Acquire/release lock */
-	list_add_tail(&entry->node, &acpi_prt.entries);
-	acpi_prt.count++;
+	list_add_tail(&entry->node, &prt_list->entries);
+	prt_list->count++;
 
 	return_VALUE(0);
 }
 
+struct acpi_prt_list*
+acpi_pci_get_prt_list (void)
+{
+	acpi_status			status = AE_OK;
+	struct acpi_buffer		buffer = {0, NULL};
+	struct acpi_pci_routing_table	*prt = NULL;
+	struct acpi_pci_routing_table	*entry = NULL;
+	struct acpi_prt_list		*prt_list = NULL;
+	struct acpi_prt_ref		*prt_ref_entry = NULL;
+	struct list_head		*node = NULL;
+   
+	ACPI_FUNCTION_TRACE("acpi_pci_irq_get_prt_list");
+   
+	/* Create a brand new acpi_prt_list */
+	prt_list = kmalloc(sizeof(struct acpi_prt_list), GFP_KERNEL);
+	if (!prt_list)
+		return_PTR(NULL);
+	memset(prt_list, 0, sizeof(struct acpi_prt_list));
+   
+	prt_list->count = 0;
+	INIT_LIST_HEAD(&prt_list->entries);
+   
+	/* iterate over all entries in acpi_prt_ref_list, extracting the current _PRT entries */
+	list_for_each(node, &acpi_prt_ref_list.entries) {
+		prt_ref_entry = list_entry(node, struct acpi_prt_ref, node);
+   
+		/* 
+		 * Evaluate this _PRT and add its entries to our local list (prt_list).
+		 */
+
+		buffer.length = 0;
+		buffer.pointer = NULL;
+		status = acpi_get_irq_routing_table(prt_ref_entry->handle, &buffer);
+		if (status != AE_BUFFER_OVERFLOW) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
+				acpi_format_exception(status)));
+			kfree(prt_list);
+			return_PTR(NULL);
+		}
+
+		prt = kmalloc(buffer.length, GFP_KERNEL);
+		if (!prt) {
+			kfree(prt_list);
+			return_VALUE(NULL);
+		}
+		memset(prt, 0, buffer.length);
+		buffer.pointer = prt;
+
+		status = acpi_get_irq_routing_table(prt_ref_entry->handle, &buffer);
+		if (ACPI_FAILURE(status)) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
+				acpi_format_exception(status)));
+			kfree(buffer.pointer);
+			kfree(prt_list);
+			return_PTR(NULL);
+		}
+
+		entry = prt;
+
+		while (entry && (entry->length > 0)) {
+			acpi_pci_irq_add_entry(prt_list, prt_ref_entry->handle, prt_ref_entry->segment, 
+				prt_ref_entry->bus, entry);
+			entry = (struct acpi_pci_routing_table *)
+				((unsigned long) entry + entry->length);
+		}
+
+		kfree(prt);
+	}
+
+	return_PTR(prt_list);
+}
+
+int 
+acpi_pci_destroy_prt_list (struct acpi_prt_list* prt_list) {
+	struct list_head	*node = NULL;
+	struct list_head	*tmp = NULL;
+	struct acpi_prt_entry	*entry = NULL;
+   
+	ACPI_FUNCTION_TRACE("acpi_pci_irq_destroy_prt_list");
+
+	list_for_each_safe(node, tmp, &prt_list->entries) {
+		entry = list_entry(node, struct acpi_prt_entry, node);
+		list_del(node);
+		kfree(entry);
+	}
+	kfree(prt_list);
+   
+	return_VALUE(0);
+}	  
+  
+int
+acpi_pci_commit_prt_list (struct acpi_prt_list* prt_list) {
+
+	ACPI_FUNCTION_TRACE("acpi_pci_irq_commit_prt_list");
+   
+	if (acpi_prt != NULL) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Attempt to commit acpi_prt twice\n"));
+		return_VALUE(-ENODEV);
+	}
+
+	acpi_prt = prt_list;
+	return_VALUE(0);
+}
 
 int
 acpi_pci_irq_add_prt (
@@ -164,21 +289,20 @@
 	int			segment,
 	int			bus)
 {
-	acpi_status			status = AE_OK;
-	char				pathname[ACPI_PATHNAME_MAX] = {0};
-	struct acpi_buffer		buffer = {0, NULL};
-	struct acpi_pci_routing_table	*prt = NULL;
-	struct acpi_pci_routing_table	*entry = NULL;
-	static int			first_time = 1;
+	static int		first_time = 1;
+	struct acpi_prt_ref	*entry = NULL;
+	struct acpi_buffer	buffer = {0, NULL};
+	char			pathname[ACPI_PATHNAME_MAX] = {0};
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_add_prt");
 
 	if (first_time) {
-		acpi_prt.count = 0;
-		INIT_LIST_HEAD(&acpi_prt.entries);
+		acpi_prt_ref_list.count = 0;
+		INIT_LIST_HEAD(&acpi_prt_ref_list.entries);
 		first_time = 0;
 	}
 
+   
 	/* 
 	 * NOTE: We're given a 'handle' to the _PRT object's parent device
 	 *       (either a PCI root bridge or PCI-PCI bridge).
@@ -191,42 +315,19 @@
 	printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
 		pathname);
 
-	/* 
-	 * Evaluate this _PRT and add its entries to our global list (acpi_prt).
-	 */
-
-	buffer.length = 0;
-	buffer.pointer = NULL;
-	status = acpi_get_irq_routing_table(handle, &buffer);
-	if (status != AE_BUFFER_OVERFLOW) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
-			acpi_format_exception(status)));
-		return_VALUE(-ENODEV);
-	}
-
-	prt = kmalloc(buffer.length, GFP_KERNEL);
-	if (!prt)
+   
+   
+	entry = kmalloc(sizeof(struct acpi_prt_ref), GFP_KERNEL);
+	if (!entry)
 		return_VALUE(-ENOMEM);
-	memset(prt, 0, buffer.length);
-	buffer.pointer = prt;
-
-	status = acpi_get_irq_routing_table(handle, &buffer);
-	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
-			acpi_format_exception(status)));
-		kfree(buffer.pointer);
-		return_VALUE(-ENODEV);
-	}
+	memset(entry, 0, sizeof(struct acpi_prt_ref));
+   
+	entry->handle = handle;
+	entry->segment = segment;
+	entry->bus = bus;
 
-	entry = prt;
-
-	while (entry && (entry->length > 0)) {
-		acpi_pci_irq_add_entry(handle, segment, bus, entry);
-		entry = (struct acpi_pci_routing_table *)
-			((unsigned long) entry + entry->length);
-	}
-
-	kfree(prt);
+	list_add_tail(&entry->node, &acpi_prt_ref_list.entries);
+	acpi_prt_ref_list.count++;
 
 	return_VALUE(0);
 }
@@ -387,6 +488,15 @@
 }
 
 
+static void __init acpi_irq_pic_mode(void)
+{
+	acpi_irq_model = ACPI_IRQ_MODEL_PIC;
+	acpi_bus_init_irq();
+   
+        /* recalculate penalties */
+ 	acpi_pci_link_calc_penalties();
+}
+
 int __init
 acpi_pci_irq_init (void)
 {
@@ -394,26 +504,25 @@
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_init");
 
-	if (!acpi_prt.count) {
-		printk(KERN_WARNING PREFIX "ACPI tables contain no PCI IRQ "
-			"routing entries\n");
-		return_VALUE(-ENODEV);
-	}
-
-	/* Make sure all link devices have a valid IRQ. */
-	if (acpi_pci_link_check()) {
-		return_VALUE(-ENODEV);
-	}
+ 	/* Calculate IRQ penalties for each link device */
+ 	acpi_pci_link_calc_penalties();
 
 #ifdef CONFIG_X86_IO_APIC
 	/* Program IOAPICs using data from PRT entries. */
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-		mp_parse_prt();
+ 		if (mp_parse_prt()) 
+ 			acpi_irq_pic_mode();
 #endif
 #ifdef CONFIG_IOSAPIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOSAPIC)
-		iosapic_parse_prt();
+ 		if (iosapic_parse_prt())
+       			return_VALUE(-ENODEV);
 #endif
+   
+ 	/* This one is last, as a catchall */
+ 	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC)
+ 		if (pic_parse_prt()) 
+ 			return_VALUE(-ENODEV);
 
 	pci_for_each_dev(dev)
 		acpi_pci_irq_enable(dev);
--- linux-2.4.23-pre3.orig/drivers/acpi/pci_link.c	2003-08-25 12:44:41.000000000 +0100
+++ linux-2.4.23-pre3/drivers/acpi/pci_link.c	2003-09-05 18:55:42.318729480 +0100
@@ -277,6 +277,32 @@
 
 
 static int
+acpi_pci_link_try_get_current (
+	struct acpi_pci_link *link,
+	int irq)
+{
+	int result;
+
+	ACPI_FUNCTION_TRACE("acpi_pci_link_try_get_current");
+   
+	result = acpi_pci_link_get_current(link);
+	if (result && link->irq.active) 
+	{
+		return_VALUE(result);
+	}
+
+	if (!link->irq.active) 
+	{
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No active IRQ resource found\n"));
+		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));
+		link->irq.active = irq;
+	}
+   
+	return 0;
+}
+
+
+static int
 acpi_pci_link_set (
 	struct acpi_pci_link	*link,
 	int			irq)
@@ -290,7 +316,8 @@
 	struct acpi_buffer	buffer = {sizeof(resource)+1, &resource};
 	int			i = 0;
 	int			valid = 0;
-
+	int			resource_type = 0;
+   
 	ACPI_FUNCTION_TRACE("acpi_pci_link_set");
 
 	if (!link || !irq)
@@ -313,12 +340,23 @@
 		}
 	}
 
+	/* If IRQ<=15, first try with a "normal" IRQ descriptor. If that fails, try with
+	 * an extended one */
+	if (irq <= 15) {
+		resource_type = ACPI_RSTYPE_IRQ;
+	} else {
+		resource_type = ACPI_RSTYPE_EXT_IRQ;
+	}
+
+retry_programming:
+   
 	memset(&resource, 0, sizeof(resource));
 
 	/* NOTE: PCI interrupts are always level / active_low / shared. But not all
 	   interrupts > 15 are PCI interrupts. Rely on the ACPI IRQ definition for 
 	   parameters */
-	if (irq <= 15) {
+	switch(resource_type) {
+	case ACPI_RSTYPE_IRQ:
 		resource.res.id = ACPI_RSTYPE_IRQ;
 		resource.res.length = sizeof(struct acpi_resource);
 		resource.res.data.irq.edge_level = link->irq.edge_level;
@@ -326,8 +364,9 @@
 		resource.res.data.irq.shared_exclusive = ACPI_SHARED;
 		resource.res.data.irq.number_of_interrupts = 1;
 		resource.res.data.irq.interrupts[0] = irq;
-	}
-	else {
+		break;
+	   
+	case ACPI_RSTYPE_EXT_IRQ:
 		resource.res.id = ACPI_RSTYPE_EXT_IRQ;
 		resource.res.length = sizeof(struct acpi_resource);
 		resource.res.data.extended_irq.producer_consumer = ACPI_CONSUMER;
@@ -337,11 +376,22 @@
 		resource.res.data.extended_irq.number_of_interrupts = 1;
 		resource.res.data.extended_irq.interrupts[0] = irq;
 		/* ignore resource_source, it's optional */
+		break;
 	}
 	resource.end.id = ACPI_RSTYPE_END_TAG;
 
 	/* Attempt to set the resource */
 	status = acpi_set_current_resources(link->handle, &buffer);
+   
+
+	/* if we failed and IRQ <= 15, try again with an extended descriptor */
+	if (ACPI_FAILURE(status) && (resource_type == ACPI_RSTYPE_IRQ)) {
+                resource_type = ACPI_RSTYPE_EXT_IRQ;
+                printk(PREFIX "Retrying with extended IRQ descriptor\n");
+                goto retry_programming;
+	}
+  
+	/* check for total failure */
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n"));
 		return_VALUE(-ENODEV);
@@ -359,11 +409,11 @@
 	}
 
 	/* Make sure the active IRQ is the one we requested. */
-	result = acpi_pci_link_get_current(link);
+	result = acpi_pci_link_try_get_current(link, irq);
 	if (result) {
 		return_VALUE(result);
 	}
-   
+
 	if (link->irq.active != irq) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
 			"Attempt to enable at IRQ %d resulted in IRQ %d\n", 
@@ -399,23 +449,26 @@
  * as 'best bets' for PCI use.
  */
 
-static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
+static int acpi_irq_default_penalty[ACPI_MAX_IRQS] = {
 	1000000,  1000000,  1000000,    10000, 
 	  10000,        0,    10000,    10000,
 	  10000,        0,        0,        0, 
 	  10000,   100000,   100000,   100000,
 };
 
+static int acpi_irq_penalty[ACPI_MAX_IRQS] = { 0 };
 
 int
-acpi_pci_link_check (void)
+acpi_pci_link_calc_penalties (void)
 {
 	struct list_head	*node = NULL;
 	struct acpi_pci_link    *link = NULL;
 	int			i = 0;
 
-	ACPI_FUNCTION_TRACE("acpi_pci_link_check");
+	ACPI_FUNCTION_TRACE("acpi_pci_calc_penalties");
 
+	memcpy(&acpi_irq_penalty, &acpi_irq_default_penalty, sizeof(acpi_irq_default_penalty));
+   
 	/*
 	 * Update penalties to facilitate IRQ balancing.
 	 */
@@ -426,7 +479,8 @@
 			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
 			continue;
 		}
-
+		link->irq.setonboot = 0;
+	   
 		if (link->irq.active)
 			acpi_irq_penalty[link->irq.active] += 100;
 		else if (link->irq.possible_count) {
@@ -456,18 +510,18 @@
 		irq = link->irq.possible[0];
 	}
 
-		/* 
-		 * Select the best IRQ.  This is done in reverse to promote 
-		 * the use of IRQs 9, 10, 11, and >15.
-		 */
-		for (i=(link->irq.possible_count-1); i>0; i--) {
-			if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
-				irq = link->irq.possible[i];
-		}
+	/* 
+	 * Select the best IRQ.  This is done in reverse to promote 
+	 * the use of IRQs 9, 10, 11, and >15.
+	 */
+	for (i=(link->irq.possible_count-1); i>0; i--) {
+		if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
+			irq = link->irq.possible[i];
+	}
 
 	/* Attempt to enable the link device at this IRQ. */
 	if (acpi_pci_link_set(link, irq)) {
-		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",
+		printk(PREFIX "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS, please report to acpi-devel!)\n",
 			acpi_device_name(link->device),
 			acpi_device_bid(link->device));
 		return_VALUE(-ENODEV);
@@ -573,10 +627,6 @@
 		else
 			printk(" %d", link->irq.possible[i]);
 	}
-	if (!link->irq.active)
-		printk(", disabled");
-	else if (!found)
-		printk(", enabled at IRQ %d", link->irq.active);
 	printk(")\n");
 
 	/* TBD: Acquire/release lock */
--- linux-2.4.23-pre3.orig/drivers/acpi/bus.c	2003-08-25 12:44:41.000000000 +0100
+++ linux-2.4.23-pre3/drivers/acpi/bus.c	2003-09-05 18:55:42.319729328 +0100
@@ -1802,7 +1802,7 @@
                              Initialization/Cleanup
    -------------------------------------------------------------------------- */
 
-static int __init
+int
 acpi_bus_init_irq (void)
 {
 	acpi_status		status = AE_OK;
--- linux-2.4.23-pre3.orig/include/acpi/acpi_drivers.h	2003-08-25 12:44:43.000000000 +0100
+++ linux-2.4.23-pre3/include/acpi/acpi_drivers.h	2003-09-05 18:55:42.320729176 +0100
@@ -26,6 +26,9 @@
 #ifndef __ACPI_DRIVERS_H__
 #define __ACPI_DRIVERS_H__
 
+/* forward definitions */
+struct acpi_prt_list;
+
 #include <linux/acpi.h>
 #include "acpi_bus.h"
 
@@ -173,7 +176,7 @@
 #define ACPI_PCI_LINK_FILE_INFO		"info"
 #define ACPI_PCI_LINK_FILE_STATUS	"state"
 
-int acpi_pci_link_check (void);
+int acpi_pci_link_calc_penalties (void);
 int acpi_pci_link_get_irq (acpi_handle handle, int index, int* edge_level, int* active_high_low);
 int acpi_pci_link_init (void);
 void acpi_pci_link_exit (void);
@@ -181,6 +184,9 @@
 /* ACPI PCI Interrupt Routing (pci_irq.c) */
 
 int acpi_pci_irq_add_prt (acpi_handle handle, int segment, int bus);
+int acpi_pci_commit_prt_list (struct acpi_prt_list* prt_list);
+int acpi_pci_destroy_prt_list (struct acpi_prt_list* prt_list);
+struct acpi_prt_list* acpi_pci_get_prt_list (void);
 
 /* ACPI PCI Device Binding (pci_bind.c) */
 
--- linux-2.4.23-pre3.orig/include/linux/acpi.h	2003-08-25 12:44:44.000000000 +0100
+++ linux-2.4.23-pre3/include/linux/acpi.h	2003-09-05 18:55:42.321729024 +0100
@@ -401,7 +401,7 @@
 	struct list_head	entries;
 };
 
-extern struct acpi_prt_list	acpi_prt;
+extern struct acpi_prt_list*	acpi_prt;
 
 struct pci_dev;
 
--- linux-2.4.23-pre3.orig/include/acpi/acpi_bus.h	2003-08-25 12:44:43.000000000 +0100
+++ linux-2.4.23-pre3/include/acpi/acpi_bus.h	2003-09-05 18:55:42.322728872 +0100
@@ -309,6 +309,7 @@
 int acpi_init (void);
 void acpi_exit (void);
 
+int acpi_bus_init_irq (void);
 
 #endif /*CONFIG_ACPI_BUS*/
 
---- END linux-2.4.23-pre3-acpi-picmode-5.patch ----




Here is the patch for 2.6.0-test4:




---- BEGIN linux-2.6.0-test4-acpi-picmode-5.patch ----
--- linux-2.6.0-test4.orig/arch/i386/kernel/mpparse.c	2003-08-23 00:53:52.000000000 +0100
+++ linux-2.6.0-test4/arch/i386/kernel/mpparse.c	2003-08-30 23:16:07.000000000 +0100
@@ -1073,10 +1073,11 @@
 
 #ifdef CONFIG_ACPI_PCI
 
-void __init mp_parse_prt (void)
+int __init mp_parse_prt (void)
 {
 	struct list_head	*node = NULL;
 	struct acpi_prt_entry	*entry = NULL;
+ 	struct acpi_prt_list	*prt_list = NULL;
 	int			ioapic = -1;
 	int			ioapic_pin = 0;
 	int			irq = 0;
@@ -1084,16 +1085,31 @@
 	int			edge_level = 0;
 	int			active_high_low = 0;
 
+ 	/* Get the current PRT */
+ 	prt_list = acpi_pci_get_prt_list();
+   
+ 	if (!prt_list->count) {
+ 		acpi_pci_destroy_prt_list(prt_list);
+ 		printk(KERN_WARNING PREFIX "ACPI tables contain no IO-APIC PCI IRQ "
+ 			"routing entries\n");
+ 		return_VALUE(-ENODEV);
+ 	}
+   
 	/*
 	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
 	 * routing for all entries.
 	 */
-	list_for_each(node, &acpi_prt.entries) {
+	list_for_each(node, &prt_list->entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
 
 		/* Need to get irq for dynamic entry */
 		if (entry->link.handle) {
 			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
+		   
 			if (!irq)
 				continue;
 		}
@@ -1113,8 +1129,6 @@
 			continue;
 		ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start;
 
-		if (!ioapic && (irq < 16))
-			irq += 16;
 		/* 
 		 * Avoid pin reprogramming.  PRTs typically include entries  
 		 * with redundant pin->irq mappings (but unique PCI devices);
@@ -1146,6 +1160,11 @@
 			mp_ioapic_routing[ioapic].apic_id, ioapic_pin, 
 			entry->irq);
 	}
+   
+ 	/* if we get here, the PRT was fine. commit it */
+ 	acpi_pci_commit_prt_list(prt_list);
+   
+	return 0;
 }
 
 #endif /*CONFIG_ACPI_PCI*/
--- linux-2.6.0-test4.orig/arch/i386/kernel/acpi/pic.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-test4/arch/i386/kernel/acpi/pic.c	2003-08-30 23:25:01.000000000 +0100
@@ -0,0 +1,102 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2003 Andrew de Quincey - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/bootmem.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/acpi.h>
+
+#ifdef CONFIG_ACPI_PCI
+
+extern void eisa_set_level_irq(unsigned int irq);
+
+int __init pic_parse_prt (void)
+{
+	struct list_head	*node = NULL;
+	struct acpi_prt_entry	*entry = NULL;
+	struct acpi_prt_list	*prt_list = NULL;
+	int			edge_level = 0;
+	int			active_high_low = 0;
+	int			irq = 0;
+	int			programmed[16];
+
+	/* Get the current PRT */
+	prt_list = acpi_pci_get_prt_list();
+   
+	if (!prt_list->count) {
+		acpi_pci_destroy_prt_list(prt_list);
+		printk(KERN_WARNING PREFIX "ACPI tables contain no PIC PCI IRQ "
+			"routing entries\n");
+		return_VALUE(-ENODEV);
+	}
+
+	/* mark all IRQs as unprogrammed */
+	memset(programmed, 0, sizeof(programmed));
+   
+	/*
+	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
+	 * IRQs if necessary.
+	 */
+	list_for_each(node, &prt_list->entries) {
+		entry = list_entry(node, struct acpi_prt_entry, node);
+
+		/* Need to get irq for dynamic entry */
+		if (entry->link.handle) {
+			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
+ 			if (!irq) 
+				continue;
+		}
+	   
+		/* sanity check + update entry */
+		if ((irq < 0) || (irq > 15)) {
+			printk(KERN_ERR "Invalid IRQ (%i) passed to PIC programming code\n", irq);
+			entry->irq = 0;
+			continue;
+		}
+		entry->irq = irq;
+
+		/* check if it has already been dealt with */
+		if (programmed[irq]) {
+			printk(KERN_DEBUG "PIC: IRQ (%i) already programmed\n", irq);
+			continue;
+		}
+		programmed[irq] = 1;
+
+		/* program it */
+		if (edge_level) {
+			eisa_set_level_irq(irq);
+		}
+	   
+		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> IRQ %d Mode %d Trigger %d\n",
+			entry->id.segment, entry->id.bus, 
+			entry->id.device, ('A' + entry->pin), 
+			entry->irq, edge_level, active_high_low);
+	}
+	
+	/* if we get here, the PRT was fine. commit it */
+	acpi_pci_commit_prt_list(prt_list);
+   
+	return 0;
+}
+
+#endif /*CONFIG_ACPI_PCI*/
--- linux-2.6.0-test4.orig/arch/i386/kernel/acpi/Makefile	2003-08-23 00:55:40.000000000 +0100
+++ linux-2.6.0-test4/arch/i386/kernel/acpi/Makefile	2003-08-30 23:25:30.000000000 +0100
@@ -1,3 +1,3 @@
-obj-$(CONFIG_ACPI_BOOT)		:= boot.o
+obj-$(CONFIG_ACPI_BOOT)		:= boot.o pic.o
 obj-$(CONFIG_ACPI_SLEEP)	+= sleep.o wakeup.o
 
--- linux-2.6.0-test4.orig/include/asm-i386/mpspec.h	2003-08-23 00:50:21.000000000 +0100
+++ linux-2.6.0-test4/include/asm-i386/mpspec.h	2003-08-30 23:12:41.000000000 +0100
@@ -37,7 +37,7 @@
 extern void mp_register_ioapic (u8 id, u32 address, u32 irq_base);
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 global_irq);
 extern void mp_config_acpi_legacy_irqs (void);
-extern void mp_parse_prt (void);
+extern int mp_parse_prt (void);
 
 #ifdef CONFIG_X86_IO_APIC
 extern void mp_config_ioapic_for_sci(int irq);
--- linux-2.6.0-test4.orig/include/asm-i386/acpi.h	2003-08-23 00:59:31.000000000 +0100
+++ linux-2.6.0-test4/include/asm-i386/acpi.h	2003-08-30 23:27:35.000000000 +0100
@@ -151,6 +151,9 @@
 /* early initialization routine */
 extern void acpi_reserve_bootmem(void);
 
+/* ACPI-based PIC initialisation */
+extern int pic_parse_prt (void);
+
 #endif /*CONFIG_ACPI_SLEEP*/
 
 #endif /*__KERNEL__*/
--- linux-2.6.0-test4.orig/arch/x86_64/kernel/mpparse.c	2003-08-23 00:53:53.000000000 +0100
+++ linux-2.6.0-test4/arch/x86_64/kernel/mpparse.c	2003-08-31 01:08:55.000000000 +0100
@@ -889,16 +889,31 @@
 	int			edge_level = 0;
 	int			active_high_low = 0;
 
+ 	/* Get the current PRT */
+ 	prt_list = acpi_pci_get_prt_list();
+   
+ 	if (!prt_list->count) {
+ 		acpi_pci_destroy_prt_list(prt_list);
+ 		printk(KERN_WARNING PREFIX "ACPI tables contain no IO-APIC PCI IRQ "
+ 			"routing entries\n");
+ 		return_VALUE(-ENODEV);
+ 	}
+   
 	/*
 	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
 	 * routing for all static (IOAPIC-direct) entries.
 	 */
-	list_for_each(node, &acpi_prt.entries) {
+	list_for_each(node, &acpi_prt->entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
 
 		/* Need to get irq for dynamic entry */
 		if (entry->link.handle) {
 			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
+
 			if (!irq)
 				continue;
 		} else {
@@ -949,8 +964,11 @@
 			mp_ioapic_routing[ioapic].apic_id, ioapic_pin, vector, 
 			entry->irq);
 	}
+   
+ 	/* if we get here, the PRT was fine. commit it */
+ 	acpi_pci_commit_prt_list(prt_list);
 	
-	return;
+	return 0;
 }
 
 #endif /*CONFIG_ACPI_PCI*/
--- linux-2.6.0-test4.orig/arch/x86_64/kernel/acpi/pic.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-test4/arch/x86_64/kernel/acpi/pic.c	2003-08-31 00:16:21.000000000 +0100
@@ -0,0 +1,102 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2003 Andrew de Quincey - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/bootmem.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/acpi.h>
+
+#ifdef CONFIG_ACPI_PCI
+
+extern void eisa_set_level_irq(unsigned int irq);
+
+int __init pic_parse_prt (void)
+{
+	struct list_head	*node = NULL;
+	struct acpi_prt_entry	*entry = NULL;
+	struct acpi_prt_list	*prt_list = NULL;
+	int			edge_level = 0;
+	int			active_high_low = 0;
+	int			irq = 0;
+	int			programmed[16];
+
+	/* Get the current PRT */
+	prt_list = acpi_pci_get_prt_list();
+   
+	if (!prt_list->count) {
+		acpi_pci_destroy_prt_list(prt_list);
+		printk(KERN_WARNING PREFIX "ACPI tables contain no PIC PCI IRQ "
+			"routing entries\n");
+		return_VALUE(-ENODEV);
+	}
+
+	/* mark all IRQs as unprogrammed */
+	memset(programmed, 0, sizeof(programmed));
+   
+	/*
+	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
+	 * IRQs if necessary.
+	 */
+	list_for_each(node, &prt_list->entries) {
+		entry = list_entry(node, struct acpi_prt_entry, node);
+
+		/* Need to get irq for dynamic entry */
+		if (entry->link.handle) {
+			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
+ 			if (!irq) 
+				continue;
+		}
+	   
+		/* sanity check + update entry */
+		if ((irq < 0) || (irq > 15)) {
+			printk(KERN_ERR "Invalid IRQ (%i) passed to PIC programming code\n", irq);
+			entry->irq = 0;
+			continue;
+		}
+		entry->irq = irq;
+
+		/* check if it has already been dealt with */
+		if (programmed[irq]) {
+			printk(KERN_DEBUG "PIC: IRQ (%i) already programmed\n", irq);
+			continue;
+		}
+		programmed[irq] = 1;
+
+		/* program it */
+		if (edge_level) {
+			eisa_set_level_irq(irq);
+		}
+	   
+		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> IRQ %d Mode %d Trigger %d\n",
+			entry->id.segment, entry->id.bus, 
+			entry->id.device, ('A' + entry->pin), 
+			entry->irq, edge_level, active_high_low);
+	}
+	
+	/* if we get here, the PRT was fine. commit it */
+	acpi_pci_commit_prt_list(prt_list);
+   
+	return 0;
+}
+
+#endif /*CONFIG_ACPI_PCI*/
--- linux-2.6.0-test4.orig/arch/x86_64/kernel/acpi/Makefile	2003-08-23 00:56:20.000000000 +0100
+++ linux-2.6.0-test4/arch/x86_64/kernel/acpi/Makefile	2003-08-31 00:16:26.000000000 +0100
@@ -1,3 +1,3 @@
-obj-$(CONFIG_ACPI_BOOT)		:= boot.o
+obj-$(CONFIG_ACPI_BOOT)		:= boot.o pic.o
 obj-$(CONFIG_ACPI_SLEEP)	+= sleep.o wakeup.o
 
--- linux-2.6.0-test4.orig/include/asm-x86_64/mpspec.h	2003-08-23 00:55:14.000000000 +0100
+++ linux-2.6.0-test4/include/asm-x86_64/mpspec.h	2003-08-31 00:15:38.000000000 +0100
@@ -190,7 +190,7 @@
 extern void mp_register_ioapic (u8 id, u32 address, u32 irq_base);
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 global_irq);
 extern void mp_config_acpi_legacy_irqs (void);
-extern void mp_parse_prt (void);
+extern int mp_parse_prt (void);
 #endif /*CONFIG_X86_IO_APIC*/
 #endif
 
--- linux-2.6.0-test4.orig/include/asm-x86_64/acpi.h	2003-08-23 00:57:46.000000000 +0100
+++ linux-2.6.0-test4/include/asm-x86_64/acpi.h	2003-08-31 00:57:15.000000000 +0100
@@ -146,6 +146,9 @@
 #define BROKEN_ACPI_Sx		0x0001
 #define BROKEN_INIT_AFTER_S1	0x0002
 
+/* ACPI-based PIC initialisation */
+extern int pic_parse_prt (void);
+
 #endif /*__KERNEL__*/
 
 #endif /*_ASM_ACPI_H*/
--- linux-2.6.0-test4.orig/arch/ia64/kernel/iosapic.c	2003-08-23 00:55:37.000000000 +0100
+++ linux-2.6.0-test4/arch/ia64/kernel/iosapic.c	2003-08-31 00:59:55.000000000 +0100
@@ -680,7 +680,7 @@
 
 #ifdef CONFIG_ACPI_PCI
 
-void __init
+int __init
 iosapic_parse_prt (void)
 {
 	struct acpi_prt_entry *entry;
@@ -690,8 +690,19 @@
 	char pci_id[16];
 	struct hw_interrupt_type *irq_type = &irq_type_iosapic_level;
 	irq_desc_t *idesc;
+ 	struct acpi_prt_list	*prt_list = NULL;
 
-	list_for_each(node, &acpi_prt.entries) {
+ 	/* Get the current PRT */
+ 	prt_list = acpi_pci_get_prt_list();
+   
+ 	if (!prt_list->count) {
+ 		acpi_pci_destroy_prt_list(prt_list);
+ 		printk(KERN_WARNING PREFIX "ACPI tables contain no IO-APIC PCI IRQ "
+ 			"routing entries\n");
+ 		return_VALUE(-ENODEV);
+ 	}
+   
+	list_for_each(node, &prt_list->entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
 
 		/* We're only interested in static (non-link) entries.  */
@@ -729,6 +740,10 @@
 				      IOSAPIC_LEVEL);
 
 	}
+   
+ 	/* if we get here, the PRT was fine. commit it */
+ 	acpi_pci_commit_prt_list(prt_list);
+	return 0;
 }
 
 #endif /* CONFIG_ACPI */
--- linux-2.6.0-test4.orig/include/asm-ia64/iosapic.h	2003-08-23 00:56:34.000000000 +0100
+++ linux-2.6.0-test4/include/asm-ia64/iosapic.h	2003-08-31 00:53:24.000000000 +0100
@@ -57,7 +57,7 @@
 				    unsigned int gsi_base);
 extern int gsi_to_vector (unsigned int gsi);
 extern int gsi_to_irq (unsigned int gsi);
-extern void __init iosapic_parse_prt (void);
+extern int __init iosapic_parse_prt (void);
 extern void iosapic_enable_intr (unsigned int vector);
 extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity,
 				  unsigned long trigger);
--- linux-2.6.0-test4.orig/include/asm-ia64/acpi.h	2003-08-23 00:59:27.000000000 +0100
+++ linux-2.6.0-test4/include/asm-ia64/acpi.h	2003-09-01 17:01:41.000000000 +0100
@@ -112,6 +112,9 @@
 extern int __initdata nid_to_pxm_map[NR_NODES];
 #endif
 
+/* ia64 machines don't have PIC controllers */
+static inline int pic_parse_prt(void) { return -1; }
+
 #endif /*__KERNEL__*/
 
 #endif /*_ASM_ACPI_H*/
--- linux-2.6.0-test4.orig/drivers/acpi/pci_irq.c	2003-08-23 00:55:13.000000000 +0100
+++ linux-2.6.0-test4/drivers/acpi/pci_irq.c	2003-09-03 23:21:04.000000000 +0100
@@ -48,7 +48,22 @@
 #define _COMPONENT		ACPI_PCI_COMPONENT
 ACPI_MODULE_NAME		("pci_irq")
 
-struct acpi_prt_list		acpi_prt;
+struct acpi_prt_list*		acpi_prt = NULL;
+
+struct acpi_prt_ref {
+	struct list_head	node;
+	struct acpi_device	*device;
+	acpi_handle		handle;
+	int segment;
+	int bus;
+};
+
+struct acpi_prt_ref_list {
+	int			count;
+	struct list_head	entries;
+};				
+
+struct acpi_prt_ref_list acpi_prt_ref_list;
 
 #ifdef CONFIG_X86
 extern void eisa_set_level_irq(unsigned int irq);
@@ -71,13 +86,19 @@
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_find_prt_entry");
 
+	/* ensure we're not called before the routing table has been determined */
+	if (acpi_prt == NULL) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Called before acpi_prt determined"));
+		return_PTR(NULL);
+ 	}
+
 	/*
 	 * Parse through all PRT entries looking for a match on the specified
 	 * PCI device's segment, bus, device, and pin (don't care about func).
 	 *
 	 * TBD: Acquire/release lock
 	 */
-	list_for_each(node, &acpi_prt.entries) {
+	list_for_each(node, &acpi_prt->entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
 		if ((segment == entry->id.segment) 
 			&& (bus == entry->id.bus) 
@@ -93,6 +114,7 @@
 
 static int
 acpi_pci_irq_add_entry (
+	struct acpi_prt_list*		prt_list,
 	acpi_handle			handle,
 	int				segment,
 	int				bus,
@@ -149,34 +171,137 @@
 		('A' + entry->pin), prt->source, entry->link.index));
 
 	/* TBD: Acquire/release lock */
-	list_add_tail(&entry->node, &acpi_prt.entries);
-	acpi_prt.count++;
+	list_add_tail(&entry->node, &prt_list->entries);
+	prt_list->count++;
 
 	return_VALUE(0);
 }
 
 
+struct acpi_prt_list*
+acpi_pci_get_prt_list (void)
+{
+	acpi_status			status = AE_OK;
+	struct acpi_buffer		buffer = {0, NULL};
+	struct acpi_pci_routing_table	*prt = NULL;
+	struct acpi_pci_routing_table	*entry = NULL;
+	struct acpi_prt_list		*prt_list = NULL;
+	struct acpi_prt_ref		*prt_ref_entry = NULL;
+	struct list_head		*node = NULL;
+   
+	ACPI_FUNCTION_TRACE("acpi_pci_irq_get_prt_list");
+   
+	/* Create a brand new acpi_prt_list */
+	prt_list = kmalloc(sizeof(struct acpi_prt_list), GFP_KERNEL);
+	if (!prt_list)
+		return_PTR(NULL);
+	memset(prt_list, 0, sizeof(struct acpi_prt_list));
+   
+	prt_list->count = 0;
+	INIT_LIST_HEAD(&prt_list->entries);
+   
+	/* iterate over all entries in acpi_prt_ref_list, extracting the current _PRT entries */
+	list_for_each(node, &acpi_prt_ref_list.entries) {
+		prt_ref_entry = list_entry(node, struct acpi_prt_ref, node);
+   
+		/* 
+		 * Evaluate this _PRT and add its entries to our local list (prt_list).
+		 */
+
+		buffer.length = 0;
+		buffer.pointer = NULL;
+		status = acpi_get_irq_routing_table(prt_ref_entry->handle, &buffer);
+		if (status != AE_BUFFER_OVERFLOW) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
+				acpi_format_exception(status)));
+			kfree(prt_list);
+			return_PTR(NULL);
+		}
+
+		prt = kmalloc(buffer.length, GFP_KERNEL);
+		if (!prt) {
+			kfree(prt_list);
+			return_VALUE(NULL);
+		}
+		memset(prt, 0, buffer.length);
+		buffer.pointer = prt;
+
+		status = acpi_get_irq_routing_table(prt_ref_entry->handle, &buffer);
+		if (ACPI_FAILURE(status)) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
+				acpi_format_exception(status)));
+			kfree(buffer.pointer);
+			kfree(prt_list);
+			return_PTR(NULL);
+		}
+
+		entry = prt;
+
+		while (entry && (entry->length > 0)) {
+			acpi_pci_irq_add_entry(prt_list, prt_ref_entry->handle, prt_ref_entry->segment, 
+				prt_ref_entry->bus, entry);
+			entry = (struct acpi_pci_routing_table *)
+				((unsigned long) entry + entry->length);
+		}
+
+		kfree(prt);
+	}
+
+	return_PTR(prt_list);
+}
+
+int 
+acpi_pci_destroy_prt_list (struct acpi_prt_list* prt_list) {
+	struct list_head	*node = NULL;
+	struct list_head	*tmp = NULL;
+	struct acpi_prt_entry	*entry = NULL;
+   
+	ACPI_FUNCTION_TRACE("acpi_pci_irq_destroy_prt_list");
+
+	list_for_each_safe(node, tmp, &prt_list->entries) {
+		entry = list_entry(node, struct acpi_prt_entry, node);
+		list_del(node);
+		kfree(entry);
+	}
+	kfree(prt_list);
+   
+	return_VALUE(0);
+}	  
+  
+int
+acpi_pci_commit_prt_list (struct acpi_prt_list* prt_list) {
+
+	ACPI_FUNCTION_TRACE("acpi_pci_irq_commit_prt_list");
+   
+	if (acpi_prt != NULL) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Attempt to commit acpi_prt twice\n"));
+		return_VALUE(-ENODEV);
+	}
+
+	acpi_prt = prt_list;
+	return_VALUE(0);
+}
+
 int
 acpi_pci_irq_add_prt (
 	acpi_handle		handle,
 	int			segment,
 	int			bus)
 {
-	acpi_status			status = AE_OK;
-	char				pathname[ACPI_PATHNAME_MAX] = {0};
-	struct acpi_buffer		buffer = {0, NULL};
-	struct acpi_pci_routing_table	*prt = NULL;
-	struct acpi_pci_routing_table	*entry = NULL;
-	static int			first_time = 1;
+	static int		first_time = 1;
+	struct acpi_prt_ref	*entry = NULL;
+	struct acpi_buffer	buffer = {0, NULL};
+	char			pathname[ACPI_PATHNAME_MAX] = {0};
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_add_prt");
 
 	if (first_time) {
-		acpi_prt.count = 0;
-		INIT_LIST_HEAD(&acpi_prt.entries);
+		acpi_prt_ref_list.count = 0;
+		INIT_LIST_HEAD(&acpi_prt_ref_list.entries);
 		first_time = 0;
 	}
 
+   
 	/* 
 	 * NOTE: We're given a 'handle' to the _PRT object's parent device
 	 *       (either a PCI root bridge or PCI-PCI bridge).
@@ -189,42 +314,19 @@
 	printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
 		pathname);
 
-	/* 
-	 * Evaluate this _PRT and add its entries to our global list (acpi_prt).
-	 */
-
-	buffer.length = 0;
-	buffer.pointer = NULL;
-	status = acpi_get_irq_routing_table(handle, &buffer);
-	if (status != AE_BUFFER_OVERFLOW) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
-			acpi_format_exception(status)));
-		return_VALUE(-ENODEV);
-	}
-
-	prt = kmalloc(buffer.length, GFP_KERNEL);
-	if (!prt)
+   
+   
+	entry = kmalloc(sizeof(struct acpi_prt_ref), GFP_KERNEL);
+	if (!entry)
 		return_VALUE(-ENOMEM);
-	memset(prt, 0, buffer.length);
-	buffer.pointer = prt;
-
-	status = acpi_get_irq_routing_table(handle, &buffer);
-	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
-			acpi_format_exception(status)));
-		kfree(buffer.pointer);
-		return_VALUE(-ENODEV);
-	}
-
-	entry = prt;
-
-	while (entry && (entry->length > 0)) {
-		acpi_pci_irq_add_entry(handle, segment, bus, entry);
-		entry = (struct acpi_pci_routing_table *)
-			((unsigned long) entry + entry->length);
-	}
+	memset(entry, 0, sizeof(struct acpi_prt_ref));
+   
+	entry->handle = handle;
+	entry->segment = segment;
+	entry->bus = bus;
 
-	kfree(prt);
+	list_add_tail(&entry->node, &acpi_prt_ref_list.entries);
+	acpi_prt_ref_list.count++;
 
 	return_VALUE(0);
 }
@@ -383,6 +485,14 @@
 	return_VALUE(dev->irq);
 }
 
+static void __init acpi_irq_pic_mode(void)
+{
+	acpi_irq_model = ACPI_IRQ_MODEL_PIC;
+	acpi_bus_init_irq();
+   
+        /* recalculate penalties */
+ 	acpi_pci_link_calc_penalties();
+}
 
 int __init
 acpi_pci_irq_init (void)
@@ -391,27 +501,27 @@
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_init");
 
-	if (!acpi_prt.count) {
-		printk(KERN_WARNING PREFIX "ACPI tables contain no PCI IRQ "
-			"routing entries\n");
-		return_VALUE(-ENODEV);
-	}
 
-	/* Make sure all link devices have a valid IRQ. */
-	if (acpi_pci_link_check()) {
-		return_VALUE(-ENODEV);
-	}
+ 	/* Calculate IRQ penalties for each link device */
+ 	acpi_pci_link_calc_penalties();
 
 #ifdef CONFIG_X86_IO_APIC
 	/* Program IOAPICs using data from PRT entries. */
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-		mp_parse_prt();
+ 		if (mp_parse_prt()) 
+ 			acpi_irq_pic_mode();
 #endif
 #ifdef CONFIG_IOSAPIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOSAPIC)
-		iosapic_parse_prt();
+ 		if (iosapic_parse_prt())
+			return_VALUE(-ENODEV);
 #endif
-
+   
+ 	/* This one is last, as a catchall */
+ 	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC)
+ 		if (pic_parse_prt()) 
+ 			return_VALUE(-ENODEV);
+   
 	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
 		acpi_pci_irq_enable(dev);
 
--- linux-2.6.0-test4.orig/drivers/acpi/pci_link.c	2003-08-23 00:52:08.000000000 +0100
+++ linux-2.6.0-test4/drivers/acpi/pci_link.c	2003-09-04 03:29:09.529241336 +0100
@@ -281,6 +281,32 @@
 
 
 static int
+acpi_pci_link_try_get_current (
+	struct acpi_pci_link *link,
+	int irq)
+{
+	int result;
+
+	ACPI_FUNCTION_TRACE("acpi_pci_link_try_get_current");
+   
+	result = acpi_pci_link_get_current(link);
+	if (result && link->irq.active) 
+	{
+		return_VALUE(result);
+	}
+
+	if (!link->irq.active) 
+	{
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No active IRQ resource found\n"));
+		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));
+		link->irq.active = irq;
+	}
+   
+	return 0;
+}
+
+
+static int
 acpi_pci_link_set (
 	struct acpi_pci_link	*link,
 	int			irq)
@@ -294,6 +320,7 @@
 	struct acpi_buffer	buffer = {sizeof(resource)+1, &resource};
 	int			i = 0;
 	int			valid = 0;
+	int			resource_type = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_pci_link_set");
 
@@ -317,20 +344,32 @@
 		}
 	}
 
+	/* If IRQ<=15, first try with a "normal" IRQ descriptor. If that fails, try with
+	 * an extended one */
+	if (irq <= 15) {
+		resource_type = ACPI_RSTYPE_IRQ;
+	} else {
+		resource_type = ACPI_RSTYPE_EXT_IRQ;
+	}
+
+retry_programming:
+   
 	memset(&resource, 0, sizeof(resource));
 
 	/* NOTE: PCI interrupts are always level / active_low / shared. But not all
 	   interrupts > 15 are PCI interrupts. Rely on the ACPI IRQ definition for 
 	   parameters */
-	if (irq <= 15) {
+	switch(resource_type) {
+	case ACPI_RSTYPE_IRQ:
 		resource.res.id = ACPI_RSTYPE_IRQ;
 		resource.res.length = sizeof(struct acpi_resource);
 		resource.res.data.irq.edge_level = link->irq.edge_level;
 		resource.res.data.irq.active_high_low = link->irq.active_high_low;
 		resource.res.data.irq.number_of_interrupts = 1;
 		resource.res.data.irq.interrupts[0] = irq;
-	}
-	else {
+		break;
+	   
+	case ACPI_RSTYPE_EXT_IRQ:
 		resource.res.id = ACPI_RSTYPE_EXT_IRQ;
 		resource.res.length = sizeof(struct acpi_resource);
 		resource.res.data.extended_irq.producer_consumer = ACPI_CONSUMER;
@@ -339,11 +378,21 @@
 		resource.res.data.extended_irq.number_of_interrupts = 1;
 		resource.res.data.extended_irq.interrupts[0] = irq;
 		/* ignore resource_source, it's optional */
+		break;
 	}
 	resource.end.id = ACPI_RSTYPE_END_TAG;
 
 	/* Attempt to set the resource */
 	status = acpi_set_current_resources(link->handle, &buffer);
+
+	/* if we failed and IRQ <= 15, try again with an extended descriptor */
+	if (ACPI_FAILURE(status) && (resource_type == ACPI_RSTYPE_IRQ)) {
+                resource_type = ACPI_RSTYPE_EXT_IRQ;
+                printk(PREFIX "Retrying with extended IRQ descriptor\n");
+                goto retry_programming;
+	}
+  
+	/* check for total failure */
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n"));
 		return_VALUE(-ENODEV);
@@ -361,7 +410,7 @@
 	}
 
 	/* Make sure the active IRQ is the one we requested. */
-	result = acpi_pci_link_get_current(link);
+	result = acpi_pci_link_try_get_current(link, irq);
 	if (result) {
 		return_VALUE(result);
 	}
@@ -401,23 +450,26 @@
  * as 'best bets' for PCI use.
  */
 
-static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
+static int acpi_irq_default_penalty[ACPI_MAX_IRQS] = {
 	1000000,  1000000,  1000000,    10000, 
 	  10000,        0,    10000,    10000,
 	  10000,        0,        0,        0, 
 	  10000,   100000,   100000,   100000,
 };
 
+static int acpi_irq_penalty[ACPI_MAX_IRQS] = { 0 };
 
 int
-acpi_pci_link_check (void)
+acpi_pci_link_calc_penalties (void)
 {
 	struct list_head	*node = NULL;
 	struct acpi_pci_link    *link = NULL;
 	int			i = 0;
 
-	ACPI_FUNCTION_TRACE("acpi_pci_link_check");
+	ACPI_FUNCTION_TRACE("acpi_pci_link_calc_penalties");
 
+	memcpy(&acpi_irq_penalty, &acpi_irq_default_penalty, sizeof(acpi_irq_default_penalty));
+   
 	/*
 	 * Update penalties to facilitate IRQ balancing.
 	 */
@@ -428,6 +480,7 @@
 			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
 			continue;
 		}
+		link->irq.setonboot = 0;
 
 		if (link->irq.active)
 			acpi_irq_penalty[link->irq.active] += 100;
@@ -458,18 +511,18 @@
 		irq = link->irq.possible[0];
 	}
 
-		/* 
-		 * Select the best IRQ.  This is done in reverse to promote 
-		 * the use of IRQs 9, 10, 11, and >15.
-		 */
-		for (i=(link->irq.possible_count-1); i>0; i--) {
-			if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
-				irq = link->irq.possible[i];
-		}
+	/* 
+	 * Select the best IRQ.  This is done in reverse to promote 
+	 * the use of IRQs 9, 10, 11, and >15.
+	 */
+	for (i=(link->irq.possible_count-1); i>0; i--) {
+		if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
+			irq = link->irq.possible[i];
+	}
 
 	/* Attempt to enable the link device at this IRQ. */
 	if (acpi_pci_link_set(link, irq)) {
-		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",
+		printk(PREFIX "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS, please report to acpi-devel!)\n",
 			acpi_device_name(link->device),
 			acpi_device_bid(link->device));
 		return_VALUE(-ENODEV);
@@ -575,10 +628,6 @@
 		else
 			printk(" %d", link->irq.possible[i]);
 	}
-	if (!link->irq.active)
-		printk(", disabled");
-	else if (!found)
-		printk(", enabled at IRQ %d", link->irq.active);
 	printk(")\n");
 
 	/* TBD: Acquire/release lock */
--- linux-2.6.0-test4.orig/drivers/acpi/bus.c	2003-08-23 00:57:08.000000000 +0100
+++ linux-2.6.0-test4/drivers/acpi/bus.c	2003-08-30 23:23:08.000000000 +0100
@@ -536,7 +536,7 @@
                              Initialization/Cleanup
    -------------------------------------------------------------------------- */
 
-static int __init
+int
 acpi_bus_init_irq (void)
 {
 	acpi_status		status = AE_OK;
--- linux-2.6.0-test4.orig/include/acpi/acpi_drivers.h	2003-08-23 00:58:03.000000000 +0100
+++ linux-2.6.0-test4/include/acpi/acpi_drivers.h	2003-08-30 23:21:15.000000000 +0100
@@ -26,6 +26,9 @@
 #ifndef __ACPI_DRIVERS_H__
 #define __ACPI_DRIVERS_H__
 
+/* forward definitions */
+struct acpi_prt_list;
+
 #include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
 
@@ -59,12 +62,15 @@
 
 /* ACPI PCI Interrupt Link (pci_link.c) */
 
-int acpi_pci_link_check (void);
+int acpi_pci_link_calc_penalties (void);
 int acpi_pci_link_get_irq (acpi_handle handle, int index, int* edge_level, int* active_high_low);
 
 /* ACPI PCI Interrupt Routing (pci_irq.c) */
 
 int acpi_pci_irq_add_prt (acpi_handle handle, int segment, int bus);
+int acpi_pci_commit_prt_list (struct acpi_prt_list* prt_list);
+int acpi_pci_destroy_prt_list (struct acpi_prt_list* prt_list);
+struct acpi_prt_list* acpi_pci_get_prt_list (void);
 
 /* ACPI PCI Device Binding (pci_bind.c) */
 
--- linux-2.6.0-test4.orig/include/linux/acpi.h	2003-08-23 00:50:23.000000000 +0100
+++ linux-2.6.0-test4/include/linux/acpi.h	2003-08-30 23:19:27.000000000 +0100
@@ -399,7 +399,7 @@
 	struct list_head	entries;
 };
 
-extern struct acpi_prt_list	acpi_prt;
+extern struct acpi_prt_list*	acpi_prt;
 
 struct pci_dev;
 
--- linux-2.6.0-test4.orig/include/acpi/acpi_bus.h	2003-08-23 00:54:33.000000000 +0100
+++ linux-2.6.0-test4/include/acpi/acpi_bus.h	2003-08-30 23:22:02.000000000 +0100
@@ -308,6 +308,8 @@
 int acpi_create_dir(struct acpi_device *);
 void acpi_remove_dir(struct acpi_device *);
 
+int acpi_bus_init_irq (void);
+
 #endif /*CONFIG_ACPI_BUS*/
 
 #endif /*__ACPI_BUS_H__*/
---- END linux-2.6.0-test4-acpi-picmode-5.patch ----


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed)
  2003-09-05 18:58 [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed) Andrew de Quincey
@ 2003-09-05 21:35 ` Jeff Garzik
  2003-09-05 23:16   ` [ACPI] " Andrew de Quincey
  0 siblings, 1 reply; 30+ messages in thread
From: Jeff Garzik @ 2003-09-05 21:35 UTC (permalink / raw)
  To: Andrew de Quincey; +Cc: torvalds, lkml, acpi-devel, linux-acpi

Andrew de Quincey wrote:
> Hi, this is my next round of ACPI IRQ fixes. Attached are patches for linux-2.4.23-pre3 and linux-2.6.0-test4.
> 
> Please CC me on any replies. I seem to be having issues with vger.kernel.org right now.
> 
> 
> This patch addresses the following issues:
> 
> 1) ACPI now drops back to PIC mode if configuration in APIC mode fails.
> 
> 2) Removed 2 lines of erroneous code in mpparse.c which causes IO-APICs to be misconfigured.
> 
> 3) ACPI now supports PIC controllers properly.
> 
> 4) This patch includes a patch by "Jun Nakajima" <jun.nakajima@intel.com> which fixes ACPI IRQ routing for all 
> VIA motherboards I have had tested so far. I've included it in this patch as it changes one of the same files.
> 
> 5) Now retries with an extended IRQ descriptor if programming a link device with a "standard" IRQ descriptor fails.
> 
> This has already been tested successfully by multiple people.


Patch looks pretty good.  It is _very_ difficult to pick through, and 
pick apart, though.

Consider that one or more people reading your email (a) would want some 
of these fixes but (b) already have some of these fixes.

This is why we _really_ need you to split up your patches.  Multiple 
split-up patches, one per email, is preferred.  Don't worry about 
sending us too much email:  we like it like that.


As an aside, I know at least part of the VIA irq routing stuff still 
needs fixing.  For some on-board VIA southbridge devices, irq routing is 
accomplished by writing the PCI_INTERRUPT_xxx values to PCI config 
registers of the target device; for others, the normal pirq PCI config 
registers on the southbridge are used.  Alan's new irq stuff in 2.4.x 
IMO should be merged into 2.6.x soonish, as Alan's work makes a big step 
towards making it possible to fix some of the harder-to-fix irq routing 
problems.

	Jeff




^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed)
  2003-09-05 22:28     ` Jeff Garzik
@ 2003-09-05 22:28       ` Andrew Morton
  2003-09-05 22:56         ` Randy.Dunlap
  2003-09-06  0:15       ` [PATCH] 2.4.23-pre3 ACPI fixes series (1/3) Andrew de Quincey
                         ` (6 subsequent siblings)
  7 siblings, 1 reply; 30+ messages in thread
From: Andrew Morton @ 2003-09-05 22:28 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: adq_dvb, torvalds, linux-kernel, acpi-devel, linux-acpi

Jeff Garzik <jgarzik@pobox.com> wrote:
>
> Many of us have patch-applying scripts,

But only one of us documented them ;)

	http://www.zip.com.au/~akpm/linux/patches/patch-scripts-0.12/

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed)
  2003-09-05 23:16   ` [ACPI] " Andrew de Quincey
@ 2003-09-05 22:28     ` Jeff Garzik
  2003-09-05 22:28       ` Andrew Morton
                         ` (7 more replies)
  2003-09-06  0:02     ` [ACPI] Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed) Chris Wright
  1 sibling, 8 replies; 30+ messages in thread
From: Jeff Garzik @ 2003-09-05 22:28 UTC (permalink / raw)
  To: Andrew de Quincey; +Cc: torvalds, lkml, acpi-devel, linux-acpi

Andrew de Quincey wrote:
> On Friday 05 Sep 2003 10:35 pm, Jeff Garzik wrote:
>>This is why we _really_ need you to split up your patches.  Multiple
>>split-up patches, one per email, is preferred.  Don't worry about
>>sending us too much email:  we like it like that.
> 
> 
> If/when I split it up, is it acceptable to number the patches to give the 
> order they have to be applied in?

Absolutely.  It's quite common for me to receive a series of emails, all 
patches, where each successive patch has a dependency on the preceding 
one.  Linus just applies a patch series from Al Viro today which was 
presented as
	[PATCH] large dev_t - second series (1/15)
	[PATCH] large dev_t - second series (2/15)
			...
	[PATCH] large dev_t - second series (15/15)

Many of us have patch-applying scripts, which can apply an entire mbox 
full of patches.  The email subject lines, the patch, and any text you 
wrote in the email are all commited to the BitKeeper repository as a 
single changeset.


>>As an aside, I know at least part of the VIA irq routing stuff still 
>>needs fixing.  For some on-board VIA southbridge devices, irq routing is 
>>accomplished by writing the PCI_INTERRUPT_xxx values to PCI config 
>>registers of the target device; for others, the normal pirq PCI config 
>>registers on the southbridge are used.  Alan's new irq stuff in 2.4.x 
>>IMO should be merged into 2.6.x soonish, as Alan's work makes a big step 
>>towards making it possible to fix some of the harder-to-fix irq routing 
>>problems.
> 
> 
> Is this still an issue when using ACPI? Surely it should insulate the OS from 
> this chipset-specific stuff? 

Correct, proper ACPI tables on VIA will avoid this problem.

	Jeff




^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed)
  2003-09-05 22:28       ` Andrew Morton
@ 2003-09-05 22:56         ` Randy.Dunlap
  0 siblings, 0 replies; 30+ messages in thread
From: Randy.Dunlap @ 2003-09-05 22:56 UTC (permalink / raw)
  To: Andrew Morton
  Cc: jgarzik, adq_dvb, torvalds, linux-kernel, acpi-devel, linux-acpi

On Fri, 5 Sep 2003 15:28:05 -0700 Andrew Morton <akpm@osdl.org> wrote:

| Jeff Garzik <jgarzik@pobox.com> wrote:
| >
| > Many of us have patch-applying scripts,
| 
| But only one of us documented them ;)
| 
| 	http://www.zip.com.au/~akpm/linux/patches/patch-scripts-0.12/

Neil Brown documented his somewhat.  His 'wiggle' is the best
thing about his package IMO.
<http://cgi.cse.unsw.edu.au/~neilb/source/wiggle/>

Having used both of them as well as some of my own, I prefer
a mix of Andrew's and my own...

--
~Randy

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed)
  2003-09-05 21:35 ` Jeff Garzik
@ 2003-09-05 23:16   ` Andrew de Quincey
  2003-09-05 22:28     ` Jeff Garzik
  2003-09-06  0:02     ` [ACPI] Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed) Chris Wright
  0 siblings, 2 replies; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-05 23:16 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: torvalds, lkml, acpi-devel, linux-acpi

On Friday 05 Sep 2003 10:35 pm, Jeff Garzik wrote:
> Andrew de Quincey wrote:
> > Hi, this is my next round of ACPI IRQ fixes. Attached are patches for
> > linux-2.4.23-pre3 and linux-2.6.0-test4.
> >
> > Please CC me on any replies. I seem to be having issues with
> > vger.kernel.org right now.
> >
> >
> > This patch addresses the following issues:
> >
> > 1) ACPI now drops back to PIC mode if configuration in APIC mode fails.
> >
> > 2) Removed 2 lines of erroneous code in mpparse.c which causes IO-APICs
> > to be misconfigured.
> >
> > 3) ACPI now supports PIC controllers properly.
> >
> > 4) This patch includes a patch by "Jun Nakajima" <jun.nakajima@intel.com>
> > which fixes ACPI IRQ routing for all VIA motherboards I have had tested
> > so far. I've included it in this patch as it changes one of the same
> > files.
> >
> > 5) Now retries with an extended IRQ descriptor if programming a link
> > device with a "standard" IRQ descriptor fails.
> >
> > This has already been tested successfully by multiple people.
>
> Patch looks pretty good.  It is _very_ difficult to pick through, and
> pick apart, though.
>
> Consider that one or more people reading your email (a) would want some
> of these fixes but (b) already have some of these fixes.
>
> This is why we _really_ need you to split up your patches.  Multiple
> split-up patches, one per email, is preferred.  Don't worry about
> sending us too much email:  we like it like that.

If/when I split it up, is it acceptable to number the patches to give the 
order they have to be applied in? The major problem with these particular 
fixes is that they all run over the same set of files, even the same 
functions, so they all conflict with each other. 

> As an aside, I know at least part of the VIA irq routing stuff still 
> needs fixing.  For some on-board VIA southbridge devices, irq routing is 
> accomplished by writing the PCI_INTERRUPT_xxx values to PCI config 
> registers of the target device; for others, the normal pirq PCI config 
> registers on the southbridge are used.  Alan's new irq stuff in 2.4.x 
> IMO should be merged into 2.6.x soonish, as Alan's work makes a big step 
> towards making it possible to fix some of the harder-to-fix irq routing 
> problems.

Is this still an issue when using ACPI? Surely it should insulate the OS from 
this chipset-specific stuff? 

I can see what you mean from the VT8235 docs if you were programming it 
directly, but the ACPI code in all the VIA BIOSes I have analysed takes care 
of this fine.


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed)
  2003-09-05 23:16   ` [ACPI] " Andrew de Quincey
  2003-09-05 22:28     ` Jeff Garzik
@ 2003-09-06  0:02     ` Chris Wright
  2003-09-06  1:21       ` Andrew de Quincey
  1 sibling, 1 reply; 30+ messages in thread
From: Chris Wright @ 2003-09-06  0:02 UTC (permalink / raw)
  To: Andrew de Quincey; +Cc: Jeff Garzik, torvalds, lkml, acpi-devel, linux-acpi

* Andrew de Quincey (adq_dvb@lidskialf.net) wrote:
> On Friday 05 Sep 2003 10:35 pm, Jeff Garzik wrote:
> > This is why we _really_ need you to split up your patches.  Multiple
> > split-up patches, one per email, is preferred.  Don't worry about
> > sending us too much email:  we like it like that.
> 
> If/when I split it up, is it acceptable to number the patches to give the 
> order they have to be applied in? The major problem with these particular 
> fixes is that they all run over the same set of files, even the same 
> functions, so they all conflict with each other. 

Yes, please split them up.
                                                                                
I finally narrowed down to the ChangeSet 1.1046.1.424 (ACPI: Allow irqs >
15...) as cause to my current hang-on-boot problem.  Quick test to see
if this patch fixes...nope ;-(
                                                                                
thanks,
-chris

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH] 2.4.23-pre3 ACPI fixes series (1/3)
  2003-09-05 22:28     ` Jeff Garzik
  2003-09-05 22:28       ` Andrew Morton
@ 2003-09-06  0:15       ` Andrew de Quincey
  2003-09-10 11:45         ` Bernhard Rosenkraenzer
  2003-09-10 15:31         ` Daniel Egger
  2003-09-06  0:15       ` [PATCH] 2.4.23-pre3 ACPI fixes series (2/3) Andrew de Quincey
                         ` (5 subsequent siblings)
  7 siblings, 2 replies; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-06  0:15 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: torvalds, lkml, acpi-devel, linux-acpi

This patch allows ACPI to drop back to PIC mode if ACPI mode setup fails.


--- linux-2.4.23-pre3.orig/arch/i386/kernel/mpparse.c	2003-09-05 18:55:07.000000000 +0100
+++ linux-2.4.23-pre3.picmode/arch/i386/kernel/mpparse.c	2003-09-05 23:33:53.460290272 +0100
@@ -1263,10 +1263,11 @@
 
 #ifdef CONFIG_ACPI_PCI
 
-void __init mp_parse_prt (void)
+int __init mp_parse_prt (void)
 {
 	struct list_head	*node = NULL;
 	struct acpi_prt_entry	*entry = NULL;
+ 	struct acpi_prt_list	*prt_list = NULL;
 	int			ioapic = -1;
 	int			ioapic_pin = 0;
 	int			irq = 0;
@@ -1274,16 +1275,31 @@
 	int			edge_level = 0;
 	int			active_high_low = 0;
 
+ 	/* Get the current PRT */
+ 	prt_list = acpi_pci_get_prt_list();
+   
+ 	if (!prt_list->count) {
+ 		acpi_pci_destroy_prt_list(prt_list);
+ 		printk(KERN_WARNING "ACPI tables contain no IO-APIC PCI IRQ "
+ 			"routing entries\n");
+ 		return_VALUE(-ENODEV);
+ 	}
+   
 	/*
 	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
 	 * routing for all entries.
 	 */
-	list_for_each(node, &acpi_prt.entries) {
+	list_for_each(node, &prt_list->entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
 
 		/* Need to get irq for dynamic entry */
 		if (entry->link.handle) {
 			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
+		   
 			if (!irq)
 				continue;
 		}
@@ -1334,8 +1350,11 @@
 			mp_ioapic_routing[ioapic].apic_id, ioapic_pin, 
 			entry->irq);
 	}
-	
-	return;
+   
+ 	/* if we get here, the PRT was fine. commit it */
+ 	acpi_pci_commit_prt_list(prt_list);
+
+	return 0;
 }
 
 #endif /*CONFIG_ACPI_PCI*/
--- linux-2.4.23-pre3.orig/arch/i386/kernel/pic.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-pre3.picmode/arch/i386/kernel/pic.c	2003-09-05 23:33:53.461290120 +0100
@@ -0,0 +1,102 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2003 Andrew de Quincey - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/bootmem.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/acpi.h>
+
+#ifdef CONFIG_ACPI_PCI
+
+extern void eisa_set_level_irq(unsigned int irq);
+
+int __init pic_parse_prt (void)
+{
+	struct list_head	*node = NULL;
+	struct acpi_prt_entry	*entry = NULL;
+	struct acpi_prt_list	*prt_list = NULL;
+	int			edge_level = 0;
+	int			active_high_low = 0;
+	int			irq = 0;
+	int			programmed[16];
+
+	/* Get the current PRT */
+	prt_list = acpi_pci_get_prt_list();
+   
+	if (!prt_list->count) {
+		acpi_pci_destroy_prt_list(prt_list);
+		printk(KERN_WARNING "ACPI tables contain no PIC PCI IRQ "
+			"routing entries\n");
+		return_VALUE(-ENODEV);
+	}
+
+	/* mark all IRQs as unprogrammed */
+	memset(programmed, 0, sizeof(programmed));
+   
+	/*
+	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
+	 * IRQs if necessary.
+	 */
+	list_for_each(node, &prt_list->entries) {
+		entry = list_entry(node, struct acpi_prt_entry, node);
+
+		/* Need to get irq for dynamic entry */
+		if (entry->link.handle) {
+			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
+ 			if (!irq) 
+				continue;
+		}
+	   
+		/* sanity check + update entry */
+		if ((irq < 0) || (irq > 15)) {
+			printk(KERN_ERR "Invalid IRQ (%i) passed to PIC programming code\n", irq);
+			entry->irq = 0;
+			continue;
+		}
+		entry->irq = irq;
+
+		/* check if it has already been dealt with */
+		if (programmed[irq]) {
+			printk(KERN_DEBUG "PIC: IRQ (%i) already programmed\n", irq);
+			continue;
+		}
+		programmed[irq] = 1;
+
+		/* program it */
+		if (edge_level) {
+			eisa_set_level_irq(irq);
+		}
+	   
+		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> IRQ %d Mode %d Trigger %d\n",
+			entry->id.segment, entry->id.bus, 
+			entry->id.device, ('A' + entry->pin), 
+			entry->irq, edge_level, active_high_low);
+	}
+	
+	/* if we get here, the PRT was fine. commit it */
+	acpi_pci_commit_prt_list(prt_list);
+   
+	return 0;
+}
+
+#endif /*CONFIG_ACPI_PCI*/
--- linux-2.4.23-pre3.orig/arch/i386/kernel/Makefile	2003-08-25 12:44:39.000000000 +0100
+++ linux-2.4.23-pre3.picmode/arch/i386/kernel/Makefile	2003-09-05 23:33:53.461290120 +0100
@@ -36,7 +36,7 @@
 obj-$(CONFIG_X86_CPUID)		+= cpuid.o
 obj-$(CONFIG_MICROCODE)		+= microcode.o
 obj-$(CONFIG_APM)		+= apm.o
-obj-$(CONFIG_ACPI_BOOT)		+= acpi.o
+obj-$(CONFIG_ACPI_BOOT)		+= acpi.o pic.o
 obj-$(CONFIG_ACPI_SLEEP)	+= acpi_wakeup.o
 obj-$(CONFIG_ACPI_HT_ONLY)	+= acpitable.o
 obj-$(CONFIG_SMP)		+= smp.o smpboot.o trampoline.o
--- linux-2.4.23-pre3.orig/include/asm-i386/mpspec.h	2003-08-25 12:44:43.000000000 +0100
+++ linux-2.4.23-pre3.picmode/include/asm-i386/mpspec.h	2003-09-05 23:33:53.461290120 +0100
@@ -228,7 +228,7 @@
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 global_irq);
 extern void mp_config_acpi_legacy_irqs (void);
 extern void mp_config_ioapic_for_sci(int irq);
-extern void mp_parse_prt (void);
+extern int mp_parse_prt (void);
 #else /*!CONFIG_X86_IO_APIC*/
 static inline void mp_config_ioapic_for_sci(int irq) { }
 #endif /*!CONFIG_X86_IO_APIC*/
--- linux-2.4.23-pre3.orig/include/asm-i386/acpi.h	2003-08-25 12:44:43.000000000 +0100
+++ linux-2.4.23-pre3.picmode/include/asm-i386/acpi.h	2003-09-05 23:33:53.462289968 +0100
@@ -180,6 +180,9 @@
 /* early initialization routine */
 extern void acpi_reserve_bootmem(void);
 
+/* ACPI-based PIC initialisation */
+extern int pic_parse_prt (void);
+
 #endif /*CONFIG_ACPI_SLEEP*/
 
 
--- linux-2.4.23-pre3.orig/arch/x86_64/kernel/mpparse.c	2003-09-05 18:55:07.000000000 +0100
+++ linux-2.4.23-pre3.picmode/arch/x86_64/kernel/mpparse.c	2003-09-05 23:33:53.463289816 +0100
@@ -934,6 +934,7 @@
 {
 	struct list_head	*node = NULL;
 	struct acpi_prt_entry	*entry = NULL;
+	struct acpi_prt_list    *prt_list = NULL;   
 	int			vector = 0;
 	int			ioapic = -1;
 	int			ioapic_pin = 0;
@@ -942,16 +943,29 @@
 	int			edge_level = 0;
 	int			active_high_low = 0;
 
+	/* Get the current PRT */
+	prt_list = acpi_pci_get_prt_list();
+	if (!prt_list->count) {
+		acpi_pci_destroy_prt_list(prt_list);
+		printk(KERN_WARNING "ACPI tables contain no IO-APIC PCI IRQ "
+			"routing entries\n");
+		return_VALUE(-ENODEV);
+	}
+   
 	/*
 	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
 	 * routing for all static (IOAPIC-direct) entries.
 	 */
-	list_for_each(node, &acpi_prt.entries) {
+	list_for_each(node, &prt_list->entries) 
 		entry = list_entry(node, struct acpi_prt_entry, node);
 
 		/* Need to get irq for dynamic entry */
 		if (entry->link.handle) {
 			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
 			if (!irq)
 				continue;
 		} else {
@@ -998,8 +1012,11 @@
 			mp_ioapic_routing[ioapic].apic_id, ioapic_pin, vector, 
 			entry->irq);
 	}
-	
-	return;
+   
+ 	/* if we get here, the PRT was fine. commit it */
+ 	acpi_pci_commit_prt_list(prt_list);
+   
+	return 0;
 }
 
 #endif /*CONFIG_ACPI_PCI*/
--- linux-2.4.23-pre3.orig/arch/x86_64/kernel/pic.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.23-pre3.picmode/arch/x86_64/kernel/pic.c	2003-09-05 23:33:53.463289816 +0100
@@ -0,0 +1,102 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2003 Andrew de Quincey - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/bootmem.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/acpi.h>
+
+#ifdef CONFIG_ACPI_PCI
+
+extern void eisa_set_level_irq(unsigned int irq);
+
+int __init pic_parse_prt (void)
+{
+	struct list_head	*node = NULL;
+	struct acpi_prt_entry	*entry = NULL;
+	struct acpi_prt_list	*prt_list = NULL;
+	int			edge_level = 0;
+	int			active_high_low = 0;
+	int			irq = 0;
+	int			programmed[16];
+
+	/* Get the current PRT */
+	prt_list = acpi_pci_get_prt_list();
+   
+	if (!prt_list->count) {
+		acpi_pci_destroy_prt_list(prt_list);
+		printk(KERN_WARNING "ACPI tables contain no PIC PCI IRQ "
+			"routing entries\n");
+		return_VALUE(-ENODEV);
+	}
+
+	/* mark all IRQs as unprogrammed */
+	memset(programmed, 0, sizeof(programmed));
+   
+	/*
+	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
+	 * IRQs if necessary.
+	 */
+	list_for_each(node, &prt_list->entries) {
+		entry = list_entry(node, struct acpi_prt_entry, node);
+
+		/* Need to get irq for dynamic entry */
+		if (entry->link.handle) {
+			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
+ 			if (!irq) 
+				continue;
+		}
+	   
+		/* sanity check + update entry */
+		if ((irq < 0) || (irq > 15)) {
+			printk(KERN_ERR "Invalid IRQ (%i) passed to PIC programming code\n", irq);
+			entry->irq = 0;
+			continue;
+		}
+		entry->irq = irq;
+
+		/* check if it has already been dealt with */
+		if (programmed[irq]) {
+			printk(KERN_DEBUG "PIC: IRQ (%i) already programmed\n", irq);
+			continue;
+		}
+		programmed[irq] = 1;
+
+		/* program it */
+		if (edge_level) {
+			eisa_set_level_irq(irq);
+		}
+	   
+		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> IRQ %d Mode %d Trigger %d\n",
+			entry->id.segment, entry->id.bus, 
+			entry->id.device, ('A' + entry->pin), 
+			entry->irq, edge_level, active_high_low);
+	}
+	
+	/* if we get here, the PRT was fine. commit it */
+	acpi_pci_commit_prt_list(prt_list);
+   
+	return 0;
+}
+
+#endif /*CONFIG_ACPI_PCI*/
--- linux-2.4.23-pre3.orig/arch/x86_64/kernel/Makefile	2003-08-25 12:44:40.000000000 +0100
+++ linux-2.4.23-pre3.picmode/arch/x86_64/kernel/Makefile	2003-09-05 23:33:53.464289664 +0100
@@ -37,7 +37,7 @@
 obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o
 obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o
 obj-$(CONFIG_MCE) += bluesmoke.o
-obj-$(CONFIG_ACPI)		+= acpi.o
+obj-$(CONFIG_ACPI)		+= acpi.o pic.o
 obj-$(CONFIG_ACPI_SLEEP)	+= acpi_wakeup.o suspend.o
  
 
--- linux-2.4.23-pre3.orig/include/asm-x86_64/acpi.h	2003-08-25 12:44:44.000000000 +0100
+++ linux-2.4.23-pre3.picmode/include/asm-x86_64/acpi.h	2003-09-05 23:33:53.464289664 +0100
@@ -142,6 +142,9 @@
 
 extern void mp_config_ioapic_for_sci(int irq);
 
+/* ACPI-based PIC initialisation */
+extern int pic_parse_prt (void);
+
 #endif /*__KERNEL__*/
 
 #endif /*_ASM_ACPI_H*/
--- linux-2.4.23-pre3.orig/include/asm-ia64/acpi.h	2003-06-13 15:51:38.000000000 +0100
+++ linux-2.4.23-pre3.picmode/include/asm-ia64/acpi.h	2003-09-05 23:33:53.464289664 +0100
@@ -109,6 +109,9 @@
 #define MAX_PXM_DOMAINS		(256)
 #endif /* CONFIG_DISCONTIGMEM */
 
+/* ia64 machines don't have PIC controllers */
+static inline int pic_parse_prt(void) { return -1; }
+
 #endif /*__KERNEL__*/
 
 #endif /*_ASM_ACPI_H*/
--- linux-2.4.23-pre3.orig/drivers/acpi/pci_irq.c	2003-08-25 12:44:41.000000000 +0100
+++ linux-2.4.23-pre3.picmode/drivers/acpi/pci_irq.c	2003-09-05 23:33:53.465289512 +0100
@@ -50,7 +50,22 @@
 
 #define PREFIX			"PCI: "
 
-struct acpi_prt_list		acpi_prt;
+struct acpi_prt_list*		acpi_prt = NULL;
+
+struct acpi_prt_ref {
+	struct list_head	node;
+	struct acpi_device	*device;
+	acpi_handle		handle;
+	int segment;
+	int bus;
+};
+
+struct acpi_prt_ref_list {
+	int			count;
+	struct list_head	entries;
+};				
+
+struct acpi_prt_ref_list acpi_prt_ref_list;
 
 #ifdef CONFIG_X86
 extern void eisa_set_level_irq(unsigned int irq);
@@ -73,13 +88,19 @@
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_find_prt_entry");
 
+	/* ensure we're not called before the routing table has been determined */
+	if (acpi_prt == NULL) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Called before acpi_prt determined"));
+		return_PTR(NULL);
+ 	}
+   
 	/*
 	 * Parse through all PRT entries looking for a match on the specified
 	 * PCI device's segment, bus, device, and pin (don't care about func).
 	 *
 	 * TBD: Acquire/release lock
 	 */
-	list_for_each(node, &acpi_prt.entries) {
+	list_for_each(node, &acpi_prt->entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
 		if ((segment == entry->id.segment) 
 			&& (bus == entry->id.bus) 
@@ -95,6 +116,7 @@
 
 static int
 acpi_pci_irq_add_entry (
+	struct acpi_prt_list*		prt_list,
 	acpi_handle			handle,
 	int				segment,
 	int				bus,
@@ -151,12 +173,115 @@
 		('A' + entry->pin), prt->source, entry->link.index));
 
 	/* TBD: Acquire/release lock */
-	list_add_tail(&entry->node, &acpi_prt.entries);
-	acpi_prt.count++;
+	list_add_tail(&entry->node, &prt_list->entries);
+	prt_list->count++;
 
 	return_VALUE(0);
 }
 
+struct acpi_prt_list*
+acpi_pci_get_prt_list (void)
+{
+	acpi_status			status = AE_OK;
+	struct acpi_buffer		buffer = {0, NULL};
+	struct acpi_pci_routing_table	*prt = NULL;
+	struct acpi_pci_routing_table	*entry = NULL;
+	struct acpi_prt_list		*prt_list = NULL;
+	struct acpi_prt_ref		*prt_ref_entry = NULL;
+	struct list_head		*node = NULL;
+   
+	ACPI_FUNCTION_TRACE("acpi_pci_irq_get_prt_list");
+   
+	/* Create a brand new acpi_prt_list */
+	prt_list = kmalloc(sizeof(struct acpi_prt_list), GFP_KERNEL);
+	if (!prt_list)
+		return_PTR(NULL);
+	memset(prt_list, 0, sizeof(struct acpi_prt_list));
+   
+	prt_list->count = 0;
+	INIT_LIST_HEAD(&prt_list->entries);
+   
+	/* iterate over all entries in acpi_prt_ref_list, extracting the current _PRT entries */
+	list_for_each(node, &acpi_prt_ref_list.entries) {
+		prt_ref_entry = list_entry(node, struct acpi_prt_ref, node);
+   
+		/* 
+		 * Evaluate this _PRT and add its entries to our local list (prt_list).
+		 */
+
+		buffer.length = 0;
+		buffer.pointer = NULL;
+		status = acpi_get_irq_routing_table(prt_ref_entry->handle, &buffer);
+		if (status != AE_BUFFER_OVERFLOW) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
+				acpi_format_exception(status)));
+			kfree(prt_list);
+			return_PTR(NULL);
+		}
+
+		prt = kmalloc(buffer.length, GFP_KERNEL);
+		if (!prt) {
+			kfree(prt_list);
+			return_VALUE(NULL);
+		}
+		memset(prt, 0, buffer.length);
+		buffer.pointer = prt;
+
+		status = acpi_get_irq_routing_table(prt_ref_entry->handle, &buffer);
+		if (ACPI_FAILURE(status)) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
+				acpi_format_exception(status)));
+			kfree(buffer.pointer);
+			kfree(prt_list);
+			return_PTR(NULL);
+		}
+
+		entry = prt;
+
+		while (entry && (entry->length > 0)) {
+			acpi_pci_irq_add_entry(prt_list, prt_ref_entry->handle, prt_ref_entry->segment, 
+				prt_ref_entry->bus, entry);
+			entry = (struct acpi_pci_routing_table *)
+				((unsigned long) entry + entry->length);
+		}
+
+		kfree(prt);
+	}
+
+	return_PTR(prt_list);
+}
+
+int 
+acpi_pci_destroy_prt_list (struct acpi_prt_list* prt_list) {
+	struct list_head	*node = NULL;
+	struct list_head	*tmp = NULL;
+	struct acpi_prt_entry	*entry = NULL;
+   
+	ACPI_FUNCTION_TRACE("acpi_pci_irq_destroy_prt_list");
+
+	list_for_each_safe(node, tmp, &prt_list->entries) {
+		entry = list_entry(node, struct acpi_prt_entry, node);
+		list_del(node);
+		kfree(entry);
+	}
+	kfree(prt_list);
+   
+	return_VALUE(0);
+}	  
+  
+int
+acpi_pci_commit_prt_list (struct acpi_prt_list* prt_list) {
+
+	ACPI_FUNCTION_TRACE("acpi_pci_irq_commit_prt_list");
+   
+	if (acpi_prt != NULL) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Attempt to commit acpi_prt twice\n"));
+		return_VALUE(-ENODEV);
+	}
+
+	acpi_prt = prt_list;
+	return_VALUE(0);
+}
 
 int
 acpi_pci_irq_add_prt (
@@ -164,21 +289,20 @@
 	int			segment,
 	int			bus)
 {
-	acpi_status			status = AE_OK;
-	char				pathname[ACPI_PATHNAME_MAX] = {0};
-	struct acpi_buffer		buffer = {0, NULL};
-	struct acpi_pci_routing_table	*prt = NULL;
-	struct acpi_pci_routing_table	*entry = NULL;
-	static int			first_time = 1;
+	static int		first_time = 1;
+	struct acpi_prt_ref	*entry = NULL;
+	struct acpi_buffer	buffer = {0, NULL};
+	char			pathname[ACPI_PATHNAME_MAX] = {0};
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_add_prt");
 
 	if (first_time) {
-		acpi_prt.count = 0;
-		INIT_LIST_HEAD(&acpi_prt.entries);
+		acpi_prt_ref_list.count = 0;
+		INIT_LIST_HEAD(&acpi_prt_ref_list.entries);
 		first_time = 0;
 	}
 
+   
 	/* 
 	 * NOTE: We're given a 'handle' to the _PRT object's parent device
 	 *       (either a PCI root bridge or PCI-PCI bridge).
@@ -191,42 +315,19 @@
 	printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
 		pathname);
 
-	/* 
-	 * Evaluate this _PRT and add its entries to our global list (acpi_prt).
-	 */
-
-	buffer.length = 0;
-	buffer.pointer = NULL;
-	status = acpi_get_irq_routing_table(handle, &buffer);
-	if (status != AE_BUFFER_OVERFLOW) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
-			acpi_format_exception(status)));
-		return_VALUE(-ENODEV);
-	}
-
-	prt = kmalloc(buffer.length, GFP_KERNEL);
-	if (!prt)
+   
+   
+	entry = kmalloc(sizeof(struct acpi_prt_ref), GFP_KERNEL);
+	if (!entry)
 		return_VALUE(-ENOMEM);
-	memset(prt, 0, buffer.length);
-	buffer.pointer = prt;
-
-	status = acpi_get_irq_routing_table(handle, &buffer);
-	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
-			acpi_format_exception(status)));
-		kfree(buffer.pointer);
-		return_VALUE(-ENODEV);
-	}
+	memset(entry, 0, sizeof(struct acpi_prt_ref));
+   
+	entry->handle = handle;
+	entry->segment = segment;
+	entry->bus = bus;
 
-	entry = prt;
-
-	while (entry && (entry->length > 0)) {
-		acpi_pci_irq_add_entry(handle, segment, bus, entry);
-		entry = (struct acpi_pci_routing_table *)
-			((unsigned long) entry + entry->length);
-	}
-
-	kfree(prt);
+	list_add_tail(&entry->node, &acpi_prt_ref_list.entries);
+	acpi_prt_ref_list.count++;
 
 	return_VALUE(0);
 }
@@ -387,6 +488,15 @@
 }
 
 
+static void __init acpi_irq_pic_mode(void)
+{
+	acpi_irq_model = ACPI_IRQ_MODEL_PIC;
+	acpi_bus_init_irq();
+   
+        /* recalculate penalties */
+ 	acpi_pci_link_calc_penalties();
+}
+
 int __init
 acpi_pci_irq_init (void)
 {
@@ -394,26 +504,25 @@
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_init");
 
-	if (!acpi_prt.count) {
-		printk(KERN_WARNING PREFIX "ACPI tables contain no PCI IRQ "
-			"routing entries\n");
-		return_VALUE(-ENODEV);
-	}
-
-	/* Make sure all link devices have a valid IRQ. */
-	if (acpi_pci_link_check()) {
-		return_VALUE(-ENODEV);
-	}
+ 	/* Calculate IRQ penalties for each link device */
+ 	acpi_pci_link_calc_penalties();
 
 #ifdef CONFIG_X86_IO_APIC
 	/* Program IOAPICs using data from PRT entries. */
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-		mp_parse_prt();
+ 		if (mp_parse_prt()) 
+ 			acpi_irq_pic_mode();
 #endif
 #ifdef CONFIG_IOSAPIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOSAPIC)
-		iosapic_parse_prt();
+ 		if (iosapic_parse_prt())
+       			return_VALUE(-ENODEV);
 #endif
+   
+ 	/* This one is last, as a catchall */
+ 	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC)
+ 		if (pic_parse_prt()) 
+ 			return_VALUE(-ENODEV);
 
 	pci_for_each_dev(dev)
 		acpi_pci_irq_enable(dev);
--- linux-2.4.23-pre3.orig/drivers/acpi/pci_link.c	2003-09-05 23:55:06.788714928 +0100
+++ linux-2.4.23-pre3.picmode/drivers/acpi/pci_link.c	2003-09-05 23:54:45.522947816 +0100
@@ -312,13 +312,13 @@
 			return_VALUE(-EINVAL);
 		}
 	}
-
+   
 	memset(&resource, 0, sizeof(resource));
 
 	/* NOTE: PCI interrupts are always level / active_low / shared. But not all
 	   interrupts > 15 are PCI interrupts. Rely on the ACPI IRQ definition for 
 	   parameters */
-	if (irq <= 15) {
+	if (irq <= 15) {	
 		resource.res.id = ACPI_RSTYPE_IRQ;
 		resource.res.length = sizeof(struct acpi_resource);
 		resource.res.data.irq.edge_level = link->irq.edge_level;
@@ -363,7 +363,7 @@
 	if (result) {
 		return_VALUE(result);
 	}
-   
+
 	if (link->irq.active != irq) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
 			"Attempt to enable at IRQ %d resulted in IRQ %d\n", 
@@ -399,23 +399,26 @@
  * as 'best bets' for PCI use.
  */
 
-static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
+static int acpi_irq_default_penalty[ACPI_MAX_IRQS] = {
 	1000000,  1000000,  1000000,    10000, 
 	  10000,        0,    10000,    10000,
 	  10000,        0,        0,        0, 
 	  10000,   100000,   100000,   100000,
 };
 
+static int acpi_irq_penalty[ACPI_MAX_IRQS] = { 0 };
 
 int
-acpi_pci_link_check (void)
+acpi_pci_link_calc_penalties (void)
 {
 	struct list_head	*node = NULL;
 	struct acpi_pci_link    *link = NULL;
 	int			i = 0;
 
-	ACPI_FUNCTION_TRACE("acpi_pci_link_check");
+	ACPI_FUNCTION_TRACE("acpi_pci_calc_penalties");
 
+	memcpy(&acpi_irq_penalty, &acpi_irq_default_penalty, sizeof(acpi_irq_default_penalty));
+   
 	/*
 	 * Update penalties to facilitate IRQ balancing.
 	 */
@@ -426,7 +429,8 @@
 			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
 			continue;
 		}
-
+		link->irq.setonboot = 0;
+	   
 		if (link->irq.active)
 			acpi_irq_penalty[link->irq.active] += 100;
 		else if (link->irq.possible_count) {
@@ -456,18 +460,18 @@
 		irq = link->irq.possible[0];
 	}
 
-		/* 
-		 * Select the best IRQ.  This is done in reverse to promote 
-		 * the use of IRQs 9, 10, 11, and >15.
-		 */
-		for (i=(link->irq.possible_count-1); i>0; i--) {
-			if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
-				irq = link->irq.possible[i];
-		}
+	/* 
+	 * Select the best IRQ.  This is done in reverse to promote 
+	 * the use of IRQs 9, 10, 11, and >15.
+	 */
+	for (i=(link->irq.possible_count-1); i>0; i--) {
+		if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
+			irq = link->irq.possible[i];
+	}
 
 	/* Attempt to enable the link device at this IRQ. */
 	if (acpi_pci_link_set(link, irq)) {
-		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",
+		printk(PREFIX "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS, please report to acpi-devel!)\n",
 			acpi_device_name(link->device),
 			acpi_device_bid(link->device));
 		return_VALUE(-ENODEV);
--- linux-2.4.23-pre3.orig/drivers/acpi/bus.c	2003-08-25 12:44:41.000000000 +0100
+++ linux-2.4.23-pre3.picmode/drivers/acpi/bus.c	2003-09-05 23:33:53.467289208 +0100
@@ -1802,7 +1802,7 @@
                              Initialization/Cleanup
    -------------------------------------------------------------------------- */
 
-static int __init
+int
 acpi_bus_init_irq (void)
 {
 	acpi_status		status = AE_OK;
--- linux-2.4.23-pre3.orig/include/acpi/acpi_drivers.h	2003-08-25 12:44:43.000000000 +0100
+++ linux-2.4.23-pre3.picmode/include/acpi/acpi_drivers.h	2003-09-05 23:33:53.468289056 +0100
@@ -26,6 +26,9 @@
 #ifndef __ACPI_DRIVERS_H__
 #define __ACPI_DRIVERS_H__
 
+/* forward definitions */
+struct acpi_prt_list;
+
 #include <linux/acpi.h>
 #include "acpi_bus.h"
 
@@ -173,7 +176,7 @@
 #define ACPI_PCI_LINK_FILE_INFO		"info"
 #define ACPI_PCI_LINK_FILE_STATUS	"state"
 
-int acpi_pci_link_check (void);
+int acpi_pci_link_calc_penalties (void);
 int acpi_pci_link_get_irq (acpi_handle handle, int index, int* edge_level, int* active_high_low);
 int acpi_pci_link_init (void);
 void acpi_pci_link_exit (void);
@@ -181,6 +184,9 @@
 /* ACPI PCI Interrupt Routing (pci_irq.c) */
 
 int acpi_pci_irq_add_prt (acpi_handle handle, int segment, int bus);
+int acpi_pci_commit_prt_list (struct acpi_prt_list* prt_list);
+int acpi_pci_destroy_prt_list (struct acpi_prt_list* prt_list);
+struct acpi_prt_list* acpi_pci_get_prt_list (void);
 
 /* ACPI PCI Device Binding (pci_bind.c) */
 
--- linux-2.4.23-pre3.orig/include/linux/acpi.h	2003-08-25 12:44:44.000000000 +0100
+++ linux-2.4.23-pre3.picmode/include/linux/acpi.h	2003-09-05 23:33:53.469288904 +0100
@@ -401,7 +401,7 @@
 	struct list_head	entries;
 };
 
-extern struct acpi_prt_list	acpi_prt;
+extern struct acpi_prt_list*	acpi_prt;
 
 struct pci_dev;
 
--- linux-2.4.23-pre3.orig/include/acpi/acpi_bus.h	2003-08-25 12:44:43.000000000 +0100
+++ linux-2.4.23-pre3.picmode/include/acpi/acpi_bus.h	2003-09-05 23:33:53.469288904 +0100
@@ -309,6 +309,7 @@
 int acpi_init (void);
 void acpi_exit (void);
 
+int acpi_bus_init_irq (void);
 
 #endif /*CONFIG_ACPI_BUS*/
 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH] 2.4.23-pre3 ACPI fixes series (2/3)
  2003-09-05 22:28     ` Jeff Garzik
  2003-09-05 22:28       ` Andrew Morton
  2003-09-06  0:15       ` [PATCH] 2.4.23-pre3 ACPI fixes series (1/3) Andrew de Quincey
@ 2003-09-06  0:15       ` Andrew de Quincey
  2003-09-06  0:15       ` [PATCH] 2.4.23-pre3 ACPI fixes series (3/3) Andrew de Quincey
                         ` (4 subsequent siblings)
  7 siblings, 0 replies; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-06  0:15 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: torvalds, lkml, acpi-devel, linux-acpi

This patch retries IRQ programming with an extended IRQ resource descriptor
if using a standard IRQ descriptor fails.


--- linux-2.4.23-pre3.picmode/drivers/acpi/pci_link.c	2003-09-05 23:54:45.522947816 +0100
+++ linux-2.4.23-pre3.extirq/drivers/acpi/pci_link.c	2003-09-05 23:54:59.945755216 +0100
@@ -290,7 +290,8 @@
 	struct acpi_buffer	buffer = {sizeof(resource)+1, &resource};
 	int			i = 0;
 	int			valid = 0;
-
+	int			resource_type = 0;
+   
 	ACPI_FUNCTION_TRACE("acpi_pci_link_set");
 
 	if (!link || !irq)
@@ -312,13 +313,24 @@
 			return_VALUE(-EINVAL);
 		}
 	}
+ 
+	/* If IRQ<=15, first try with a "normal" IRQ descriptor. If that fails, try with
+	 * an extended one */
+	if (irq <= 15) {
+		resource_type = ACPI_RSTYPE_IRQ;
+	} else {
+		resource_type = ACPI_RSTYPE_EXT_IRQ;
+	}
+
+retry_programming:
    
 	memset(&resource, 0, sizeof(resource));
 
 	/* NOTE: PCI interrupts are always level / active_low / shared. But not all
 	   interrupts > 15 are PCI interrupts. Rely on the ACPI IRQ definition for 
 	   parameters */
-	if (irq <= 15) {	
+	switch(resource_type) {
+	case ACPI_RSTYPE_IRQ:
 		resource.res.id = ACPI_RSTYPE_IRQ;
 		resource.res.length = sizeof(struct acpi_resource);
 		resource.res.data.irq.edge_level = link->irq.edge_level;
@@ -326,8 +338,9 @@
 		resource.res.data.irq.shared_exclusive = ACPI_SHARED;
 		resource.res.data.irq.number_of_interrupts = 1;
 		resource.res.data.irq.interrupts[0] = irq;
-	}
-	else {
+		break;
+	 
+	case ACPI_RSTYPE_EXT_IRQ:
 		resource.res.id = ACPI_RSTYPE_EXT_IRQ;
 		resource.res.length = sizeof(struct acpi_resource);
 		resource.res.data.extended_irq.producer_consumer = ACPI_CONSUMER;
@@ -337,11 +350,21 @@
 		resource.res.data.extended_irq.number_of_interrupts = 1;
 		resource.res.data.extended_irq.interrupts[0] = irq;
 		/* ignore resource_source, it's optional */
+		break;
 	}
 	resource.end.id = ACPI_RSTYPE_END_TAG;
 
 	/* Attempt to set the resource */
 	status = acpi_set_current_resources(link->handle, &buffer);
+   
+	/* if we failed and IRQ <= 15, try again with an extended descriptor */
+	if (ACPI_FAILURE(status) && (resource_type == ACPI_RSTYPE_IRQ)) {
+                resource_type = ACPI_RSTYPE_EXT_IRQ;
+                printk(PREFIX "Retrying with extended IRQ descriptor\n");
+                goto retry_programming;
+	}
+
+	/* check for total failure */
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n"));
 		return_VALUE(-ENODEV);


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH] 2.4.23-pre3 ACPI fixes series (3/3)
  2003-09-05 22:28     ` Jeff Garzik
                         ` (2 preceding siblings ...)
  2003-09-06  0:15       ` [PATCH] 2.4.23-pre3 ACPI fixes series (2/3) Andrew de Quincey
@ 2003-09-06  0:15       ` Andrew de Quincey
  2003-09-06  0:57       ` [PATCH] 2.6.0-test4 ACPI fixes series (1/4) Andrew de Quincey
                         ` (3 subsequent siblings)
  7 siblings, 0 replies; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-06  0:15 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: torvalds, lkml, acpi-devel, linux-acpi

This patch is actually a patch by "Jun Nakajima" <jun.nakajima@intel.com>
When setting an IRQ link device, it checks if the value returned by _CRS is 0. 
If so, it assumes everything went OK. This fixes problems on MANY VIA bioses.
It seems to be a standard-ish way of saying "the _CRS IRQ setting cannot be read".


--- linux-2.4.23-pre3.extirq/drivers/acpi/pci_link.c	2003-09-05 23:54:59.945755216 +0100
+++ linux-2.4.23-pre3.null_crs/drivers/acpi/pci_link.c	2003-09-05 23:57:39.782456344 +0100
@@ -277,6 +277,32 @@
 
 
 static int
+acpi_pci_link_try_get_current (
+	struct acpi_pci_link *link,
+	int irq)
+{
+	int result;
+
+	ACPI_FUNCTION_TRACE("acpi_pci_link_try_get_current");
+   
+	result = acpi_pci_link_get_current(link);
+	if (result && link->irq.active) 
+	{
+		return_VALUE(result);
+	}
+
+	if (!link->irq.active) 
+	{
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No active IRQ resource found\n"));
+		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));
+		link->irq.active = irq;
+	}
+   
+	return 0;
+}
+
+
+static int
 acpi_pci_link_set (
 	struct acpi_pci_link	*link,
 	int			irq)
@@ -382,7 +408,7 @@
 	}
 
 	/* Make sure the active IRQ is the one we requested. */
-	result = acpi_pci_link_get_current(link);
+	result = acpi_pci_link_try_get_current(link, irq);
 	if (result) {
 		return_VALUE(result);
 	}
@@ -600,10 +626,6 @@
 		else
 			printk(" %d", link->irq.possible[i]);
 	}
-	if (!link->irq.active)
-		printk(", disabled");
-	else if (!found)
-		printk(", enabled at IRQ %d", link->irq.active);
 	printk(")\n");
 
 	/* TBD: Acquire/release lock */


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed)
  2003-09-06  1:21       ` Andrew de Quincey
@ 2003-09-06  0:30         ` Jeff Garzik
  2003-09-06  2:03           ` Chris Wright
  0 siblings, 1 reply; 30+ messages in thread
From: Jeff Garzik @ 2003-09-06  0:30 UTC (permalink / raw)
  To: Andrew de Quincey; +Cc: Chris Wright, lkml, acpi-devel

Andrew de Quincey wrote:
> successful dmesg
> dmesg from a failed boot
> /proc/acpi/dsdt
> /proc/interrupts


dmidecode output is also quite helpful.

	Jeff




^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH] 2.6.0-test4 ACPI fixes series (1/4)
  2003-09-05 22:28     ` Jeff Garzik
                         ` (3 preceding siblings ...)
  2003-09-06  0:15       ` [PATCH] 2.4.23-pre3 ACPI fixes series (3/3) Andrew de Quincey
@ 2003-09-06  0:57       ` Andrew de Quincey
  2003-09-06  0:57       ` [PATCH] 2.6.0-test4 ACPI fixes series (2/4) Andrew de Quincey
                         ` (2 subsequent siblings)
  7 siblings, 0 replies; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-06  0:57 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: torvalds, lkml, acpi-devel, linux-acpi

This patch allows ACPI to drop back to PIC mode if ACPI mode setup fails.


--- linux-2.6.0-test4.orig/arch/i386/kernel/mpparse.c	2003-08-23 00:53:52.000000000 +0100
+++ linux-2.6.0-test4.picmode/arch/i386/kernel/mpparse.c	2003-09-06 00:23:10.609735224 +0100
@@ -1073,10 +1073,11 @@
 
 #ifdef CONFIG_ACPI_PCI
 
-void __init mp_parse_prt (void)
+int __init mp_parse_prt (void)
 {
 	struct list_head	*node = NULL;
 	struct acpi_prt_entry	*entry = NULL;
+ 	struct acpi_prt_list	*prt_list = NULL;
 	int			ioapic = -1;
 	int			ioapic_pin = 0;
 	int			irq = 0;
@@ -1084,16 +1085,31 @@
 	int			edge_level = 0;
 	int			active_high_low = 0;
 
+ 	/* Get the current PRT */
+ 	prt_list = acpi_pci_get_prt_list();
+   
+ 	if (!prt_list->count) {
+ 		acpi_pci_destroy_prt_list(prt_list);
+ 		printk(KERN_WARNING PREFIX "ACPI tables contain no IO-APIC PCI IRQ "
+ 			"routing entries\n");
+ 		return_VALUE(-ENODEV);
+ 	}
+   
 	/*
 	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
 	 * routing for all entries.
 	 */
-	list_for_each(node, &acpi_prt.entries) {
+	list_for_each(node, &prt_list->entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
 
 		/* Need to get irq for dynamic entry */
 		if (entry->link.handle) {
 			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
+		   
 			if (!irq)
 				continue;
 		}
@@ -1115,6 +1131,7 @@
 
 		if (!ioapic && (irq < 16))
 			irq += 16;
+
 		/* 
 		 * Avoid pin reprogramming.  PRTs typically include entries  
 		 * with redundant pin->irq mappings (but unique PCI devices);
@@ -1146,6 +1163,11 @@
 			mp_ioapic_routing[ioapic].apic_id, ioapic_pin, 
 			entry->irq);
 	}
+   
+ 	/* if we get here, the PRT was fine. commit it */
+ 	acpi_pci_commit_prt_list(prt_list);
+   
+	return 0;
 }
 
 #endif /*CONFIG_ACPI_PCI*/
--- linux-2.6.0-test4.orig/arch/i386/kernel/acpi/pic.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-test4.picmode/arch/i386/kernel/acpi/pic.c	2003-09-06 00:20:15.818307560 +0100
@@ -0,0 +1,102 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2003 Andrew de Quincey - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/bootmem.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/acpi.h>
+
+#ifdef CONFIG_ACPI_PCI
+
+extern void eisa_set_level_irq(unsigned int irq);
+
+int __init pic_parse_prt (void)
+{
+	struct list_head	*node = NULL;
+	struct acpi_prt_entry	*entry = NULL;
+	struct acpi_prt_list	*prt_list = NULL;
+	int			edge_level = 0;
+	int			active_high_low = 0;
+	int			irq = 0;
+	int			programmed[16];
+
+	/* Get the current PRT */
+	prt_list = acpi_pci_get_prt_list();
+   
+	if (!prt_list->count) {
+		acpi_pci_destroy_prt_list(prt_list);
+		printk(KERN_WARNING PREFIX "ACPI tables contain no PIC PCI IRQ "
+			"routing entries\n");
+		return_VALUE(-ENODEV);
+	}
+
+	/* mark all IRQs as unprogrammed */
+	memset(programmed, 0, sizeof(programmed));
+   
+	/*
+	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
+	 * IRQs if necessary.
+	 */
+	list_for_each(node, &prt_list->entries) {
+		entry = list_entry(node, struct acpi_prt_entry, node);
+
+		/* Need to get irq for dynamic entry */
+		if (entry->link.handle) {
+			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
+ 			if (!irq) 
+				continue;
+		}
+	   
+		/* sanity check + update entry */
+		if ((irq < 0) || (irq > 15)) {
+			printk(KERN_ERR "Invalid IRQ (%i) passed to PIC programming code\n", irq);
+			entry->irq = 0;
+			continue;
+		}
+		entry->irq = irq;
+
+		/* check if it has already been dealt with */
+		if (programmed[irq]) {
+			printk(KERN_DEBUG "PIC: IRQ (%i) already programmed\n", irq);
+			continue;
+		}
+		programmed[irq] = 1;
+
+		/* program it */
+		if (edge_level) {
+			eisa_set_level_irq(irq);
+		}
+	   
+		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> IRQ %d Mode %d Trigger %d\n",
+			entry->id.segment, entry->id.bus, 
+			entry->id.device, ('A' + entry->pin), 
+			entry->irq, edge_level, active_high_low);
+	}
+	
+	/* if we get here, the PRT was fine. commit it */
+	acpi_pci_commit_prt_list(prt_list);
+   
+	return 0;
+}
+
+#endif /*CONFIG_ACPI_PCI*/
--- linux-2.6.0-test4.orig/arch/i386/kernel/acpi/Makefile	2003-08-23 00:55:40.000000000 +0100
+++ linux-2.6.0-test4.picmode/arch/i386/kernel/acpi/Makefile	2003-09-06 00:20:15.818307560 +0100
@@ -1,3 +1,3 @@
-obj-$(CONFIG_ACPI_BOOT)		:= boot.o
+obj-$(CONFIG_ACPI_BOOT)		:= boot.o pic.o
 obj-$(CONFIG_ACPI_SLEEP)	+= sleep.o wakeup.o
 
--- linux-2.6.0-test4.orig/include/asm-i386/mpspec.h	2003-08-23 00:50:21.000000000 +0100
+++ linux-2.6.0-test4.picmode/include/asm-i386/mpspec.h	2003-09-06 00:20:15.819307408 +0100
@@ -37,7 +37,7 @@
 extern void mp_register_ioapic (u8 id, u32 address, u32 irq_base);
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 global_irq);
 extern void mp_config_acpi_legacy_irqs (void);
-extern void mp_parse_prt (void);
+extern int mp_parse_prt (void);
 
 #ifdef CONFIG_X86_IO_APIC
 extern void mp_config_ioapic_for_sci(int irq);
--- linux-2.6.0-test4.orig/include/asm-i386/acpi.h	2003-08-23 00:59:31.000000000 +0100
+++ linux-2.6.0-test4.picmode/include/asm-i386/acpi.h	2003-09-06 00:20:15.819307408 +0100
@@ -151,6 +151,9 @@
 /* early initialization routine */
 extern void acpi_reserve_bootmem(void);
 
+/* ACPI-based PIC initialisation */
+extern int pic_parse_prt (void);
+
 #endif /*CONFIG_ACPI_SLEEP*/
 
 #endif /*__KERNEL__*/
--- linux-2.6.0-test4.orig/arch/x86_64/kernel/mpparse.c	2003-08-23 00:53:53.000000000 +0100
+++ linux-2.6.0-test4.picmode/arch/x86_64/kernel/mpparse.c	2003-09-06 00:20:15.820307256 +0100
@@ -889,16 +889,31 @@
 	int			edge_level = 0;
 	int			active_high_low = 0;
 
+ 	/* Get the current PRT */
+ 	prt_list = acpi_pci_get_prt_list();
+   
+ 	if (!prt_list->count) {
+ 		acpi_pci_destroy_prt_list(prt_list);
+ 		printk(KERN_WARNING PREFIX "ACPI tables contain no IO-APIC PCI IRQ "
+ 			"routing entries\n");
+ 		return_VALUE(-ENODEV);
+ 	}
+   
 	/*
 	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
 	 * routing for all static (IOAPIC-direct) entries.
 	 */
-	list_for_each(node, &acpi_prt.entries) {
+	list_for_each(node, &acpi_prt->entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
 
 		/* Need to get irq for dynamic entry */
 		if (entry->link.handle) {
 			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
+
 			if (!irq)
 				continue;
 		} else {
@@ -949,8 +964,11 @@
 			mp_ioapic_routing[ioapic].apic_id, ioapic_pin, vector, 
 			entry->irq);
 	}
+   
+ 	/* if we get here, the PRT was fine. commit it */
+ 	acpi_pci_commit_prt_list(prt_list);
 	
-	return;
+	return 0;
 }
 
 #endif /*CONFIG_ACPI_PCI*/
--- linux-2.6.0-test4.orig/arch/x86_64/kernel/acpi/pic.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.0-test4.picmode/arch/x86_64/kernel/acpi/pic.c	2003-09-06 00:20:15.820307256 +0100
@@ -0,0 +1,102 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2003 Andrew de Quincey - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/bootmem.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/acpi.h>
+
+#ifdef CONFIG_ACPI_PCI
+
+extern void eisa_set_level_irq(unsigned int irq);
+
+int __init pic_parse_prt (void)
+{
+	struct list_head	*node = NULL;
+	struct acpi_prt_entry	*entry = NULL;
+	struct acpi_prt_list	*prt_list = NULL;
+	int			edge_level = 0;
+	int			active_high_low = 0;
+	int			irq = 0;
+	int			programmed[16];
+
+	/* Get the current PRT */
+	prt_list = acpi_pci_get_prt_list();
+   
+	if (!prt_list->count) {
+		acpi_pci_destroy_prt_list(prt_list);
+		printk(KERN_WARNING PREFIX "ACPI tables contain no PIC PCI IRQ "
+			"routing entries\n");
+		return_VALUE(-ENODEV);
+	}
+
+	/* mark all IRQs as unprogrammed */
+	memset(programmed, 0, sizeof(programmed));
+   
+	/*
+	 * Parsing through the PCI Interrupt Routing Table (PRT) and program
+	 * IRQs if necessary.
+	 */
+	list_for_each(node, &prt_list->entries) {
+		entry = list_entry(node, struct acpi_prt_entry, node);
+
+		/* Need to get irq for dynamic entry */
+		if (entry->link.handle) {
+			irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low);
+			if (irq < 0) {
+				acpi_pci_destroy_prt_list(prt_list);
+				return -ENODEV;
+			}
+ 			if (!irq) 
+				continue;
+		}
+	   
+		/* sanity check + update entry */
+		if ((irq < 0) || (irq > 15)) {
+			printk(KERN_ERR "Invalid IRQ (%i) passed to PIC programming code\n", irq);
+			entry->irq = 0;
+			continue;
+		}
+		entry->irq = irq;
+
+		/* check if it has already been dealt with */
+		if (programmed[irq]) {
+			printk(KERN_DEBUG "PIC: IRQ (%i) already programmed\n", irq);
+			continue;
+		}
+		programmed[irq] = 1;
+
+		/* program it */
+		if (edge_level) {
+			eisa_set_level_irq(irq);
+		}
+	   
+		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> IRQ %d Mode %d Trigger %d\n",
+			entry->id.segment, entry->id.bus, 
+			entry->id.device, ('A' + entry->pin), 
+			entry->irq, edge_level, active_high_low);
+	}
+	
+	/* if we get here, the PRT was fine. commit it */
+	acpi_pci_commit_prt_list(prt_list);
+   
+	return 0;
+}
+
+#endif /*CONFIG_ACPI_PCI*/
--- linux-2.6.0-test4.orig/arch/x86_64/kernel/acpi/Makefile	2003-08-23 00:56:20.000000000 +0100
+++ linux-2.6.0-test4.picmode/arch/x86_64/kernel/acpi/Makefile	2003-09-06 00:20:15.833305280 +0100
@@ -1,3 +1,3 @@
-obj-$(CONFIG_ACPI_BOOT)		:= boot.o
+obj-$(CONFIG_ACPI_BOOT)		:= boot.o pic.o
 obj-$(CONFIG_ACPI_SLEEP)	+= sleep.o wakeup.o
 
--- linux-2.6.0-test4.orig/include/asm-x86_64/mpspec.h	2003-08-23 00:55:14.000000000 +0100
+++ linux-2.6.0-test4.picmode/include/asm-x86_64/mpspec.h	2003-09-06 00:20:15.833305280 +0100
@@ -190,7 +190,7 @@
 extern void mp_register_ioapic (u8 id, u32 address, u32 irq_base);
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 global_irq);
 extern void mp_config_acpi_legacy_irqs (void);
-extern void mp_parse_prt (void);
+extern int mp_parse_prt (void);
 #endif /*CONFIG_X86_IO_APIC*/
 #endif
 
--- linux-2.6.0-test4.orig/include/asm-x86_64/acpi.h	2003-08-23 00:57:46.000000000 +0100
+++ linux-2.6.0-test4.picmode/include/asm-x86_64/acpi.h	2003-09-06 00:20:15.834305128 +0100
@@ -146,6 +146,9 @@
 #define BROKEN_ACPI_Sx		0x0001
 #define BROKEN_INIT_AFTER_S1	0x0002
 
+/* ACPI-based PIC initialisation */
+extern int pic_parse_prt (void);
+
 #endif /*__KERNEL__*/
 
 #endif /*_ASM_ACPI_H*/
--- linux-2.6.0-test4.orig/arch/ia64/kernel/iosapic.c	2003-08-23 00:55:37.000000000 +0100
+++ linux-2.6.0-test4.picmode/arch/ia64/kernel/iosapic.c	2003-09-06 00:20:15.839304368 +0100
@@ -680,7 +680,7 @@
 
 #ifdef CONFIG_ACPI_PCI
 
-void __init
+int __init
 iosapic_parse_prt (void)
 {
 	struct acpi_prt_entry *entry;
@@ -690,8 +690,19 @@
 	char pci_id[16];
 	struct hw_interrupt_type *irq_type = &irq_type_iosapic_level;
 	irq_desc_t *idesc;
+ 	struct acpi_prt_list	*prt_list = NULL;
 
-	list_for_each(node, &acpi_prt.entries) {
+ 	/* Get the current PRT */
+ 	prt_list = acpi_pci_get_prt_list();
+   
+ 	if (!prt_list->count) {
+ 		acpi_pci_destroy_prt_list(prt_list);
+ 		printk(KERN_WARNING PREFIX "ACPI tables contain no IO-APIC PCI IRQ "
+ 			"routing entries\n");
+ 		return_VALUE(-ENODEV);
+ 	}
+   
+	list_for_each(node, &prt_list->entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
 
 		/* We're only interested in static (non-link) entries.  */
@@ -729,6 +740,10 @@
 				      IOSAPIC_LEVEL);
 
 	}
+   
+ 	/* if we get here, the PRT was fine. commit it */
+ 	acpi_pci_commit_prt_list(prt_list);
+	return 0;
 }
 
 #endif /* CONFIG_ACPI */
--- linux-2.6.0-test4.orig/include/asm-ia64/iosapic.h	2003-08-23 00:56:34.000000000 +0100
+++ linux-2.6.0-test4.picmode/include/asm-ia64/iosapic.h	2003-09-06 00:20:15.840304216 +0100
@@ -57,7 +57,7 @@
 				    unsigned int gsi_base);
 extern int gsi_to_vector (unsigned int gsi);
 extern int gsi_to_irq (unsigned int gsi);
-extern void __init iosapic_parse_prt (void);
+extern int __init iosapic_parse_prt (void);
 extern void iosapic_enable_intr (unsigned int vector);
 extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity,
 				  unsigned long trigger);
--- linux-2.6.0-test4.orig/include/asm-ia64/acpi.h	2003-08-23 00:59:27.000000000 +0100
+++ linux-2.6.0-test4.picmode/include/asm-ia64/acpi.h	2003-09-06 00:20:15.840304216 +0100
@@ -112,6 +112,9 @@
 extern int __initdata nid_to_pxm_map[NR_NODES];
 #endif
 
+/* ia64 machines don't have PIC controllers */
+static inline int pic_parse_prt(void) { return -1; }
+
 #endif /*__KERNEL__*/
 
 #endif /*_ASM_ACPI_H*/
--- linux-2.6.0-test4.orig/drivers/acpi/pci_irq.c	2003-08-23 00:55:13.000000000 +0100
+++ linux-2.6.0-test4.picmode/drivers/acpi/pci_irq.c	2003-09-06 00:20:15.841304064 +0100
@@ -48,7 +48,22 @@
 #define _COMPONENT		ACPI_PCI_COMPONENT
 ACPI_MODULE_NAME		("pci_irq")
 
-struct acpi_prt_list		acpi_prt;
+struct acpi_prt_list*		acpi_prt = NULL;
+
+struct acpi_prt_ref {
+	struct list_head	node;
+	struct acpi_device	*device;
+	acpi_handle		handle;
+	int segment;
+	int bus;
+};
+
+struct acpi_prt_ref_list {
+	int			count;
+	struct list_head	entries;
+};				
+
+struct acpi_prt_ref_list acpi_prt_ref_list;
 
 #ifdef CONFIG_X86
 extern void eisa_set_level_irq(unsigned int irq);
@@ -71,13 +86,19 @@
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_find_prt_entry");
 
+	/* ensure we're not called before the routing table has been determined */
+	if (acpi_prt == NULL) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Called before acpi_prt determined"));
+		return_PTR(NULL);
+ 	}
+
 	/*
 	 * Parse through all PRT entries looking for a match on the specified
 	 * PCI device's segment, bus, device, and pin (don't care about func).
 	 *
 	 * TBD: Acquire/release lock
 	 */
-	list_for_each(node, &acpi_prt.entries) {
+	list_for_each(node, &acpi_prt->entries) {
 		entry = list_entry(node, struct acpi_prt_entry, node);
 		if ((segment == entry->id.segment) 
 			&& (bus == entry->id.bus) 
@@ -93,6 +114,7 @@
 
 static int
 acpi_pci_irq_add_entry (
+	struct acpi_prt_list*		prt_list,
 	acpi_handle			handle,
 	int				segment,
 	int				bus,
@@ -149,34 +171,137 @@
 		('A' + entry->pin), prt->source, entry->link.index));
 
 	/* TBD: Acquire/release lock */
-	list_add_tail(&entry->node, &acpi_prt.entries);
-	acpi_prt.count++;
+	list_add_tail(&entry->node, &prt_list->entries);
+	prt_list->count++;
 
 	return_VALUE(0);
 }
 
 
+struct acpi_prt_list*
+acpi_pci_get_prt_list (void)
+{
+	acpi_status			status = AE_OK;
+	struct acpi_buffer		buffer = {0, NULL};
+	struct acpi_pci_routing_table	*prt = NULL;
+	struct acpi_pci_routing_table	*entry = NULL;
+	struct acpi_prt_list		*prt_list = NULL;
+	struct acpi_prt_ref		*prt_ref_entry = NULL;
+	struct list_head		*node = NULL;
+   
+	ACPI_FUNCTION_TRACE("acpi_pci_irq_get_prt_list");
+   
+	/* Create a brand new acpi_prt_list */
+	prt_list = kmalloc(sizeof(struct acpi_prt_list), GFP_KERNEL);
+	if (!prt_list)
+		return_PTR(NULL);
+	memset(prt_list, 0, sizeof(struct acpi_prt_list));
+   
+	prt_list->count = 0;
+	INIT_LIST_HEAD(&prt_list->entries);
+   
+	/* iterate over all entries in acpi_prt_ref_list, extracting the current _PRT entries */
+	list_for_each(node, &acpi_prt_ref_list.entries) {
+		prt_ref_entry = list_entry(node, struct acpi_prt_ref, node);
+   
+		/* 
+		 * Evaluate this _PRT and add its entries to our local list (prt_list).
+		 */
+
+		buffer.length = 0;
+		buffer.pointer = NULL;
+		status = acpi_get_irq_routing_table(prt_ref_entry->handle, &buffer);
+		if (status != AE_BUFFER_OVERFLOW) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
+				acpi_format_exception(status)));
+			kfree(prt_list);
+			return_PTR(NULL);
+		}
+
+		prt = kmalloc(buffer.length, GFP_KERNEL);
+		if (!prt) {
+			kfree(prt_list);
+			return_VALUE(NULL);
+		}
+		memset(prt, 0, buffer.length);
+		buffer.pointer = prt;
+
+		status = acpi_get_irq_routing_table(prt_ref_entry->handle, &buffer);
+		if (ACPI_FAILURE(status)) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
+				acpi_format_exception(status)));
+			kfree(buffer.pointer);
+			kfree(prt_list);
+			return_PTR(NULL);
+		}
+
+		entry = prt;
+
+		while (entry && (entry->length > 0)) {
+			acpi_pci_irq_add_entry(prt_list, prt_ref_entry->handle, prt_ref_entry->segment, 
+				prt_ref_entry->bus, entry);
+			entry = (struct acpi_pci_routing_table *)
+				((unsigned long) entry + entry->length);
+		}
+
+		kfree(prt);
+	}
+
+	return_PTR(prt_list);
+}
+
+int 
+acpi_pci_destroy_prt_list (struct acpi_prt_list* prt_list) {
+	struct list_head	*node = NULL;
+	struct list_head	*tmp = NULL;
+	struct acpi_prt_entry	*entry = NULL;
+   
+	ACPI_FUNCTION_TRACE("acpi_pci_irq_destroy_prt_list");
+
+	list_for_each_safe(node, tmp, &prt_list->entries) {
+		entry = list_entry(node, struct acpi_prt_entry, node);
+		list_del(node);
+		kfree(entry);
+	}
+	kfree(prt_list);
+   
+	return_VALUE(0);
+}	  
+  
+int
+acpi_pci_commit_prt_list (struct acpi_prt_list* prt_list) {
+
+	ACPI_FUNCTION_TRACE("acpi_pci_irq_commit_prt_list");
+   
+	if (acpi_prt != NULL) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Attempt to commit acpi_prt twice\n"));
+		return_VALUE(-ENODEV);
+	}
+
+	acpi_prt = prt_list;
+	return_VALUE(0);
+}
+
 int
 acpi_pci_irq_add_prt (
 	acpi_handle		handle,
 	int			segment,
 	int			bus)
 {
-	acpi_status			status = AE_OK;
-	char				pathname[ACPI_PATHNAME_MAX] = {0};
-	struct acpi_buffer		buffer = {0, NULL};
-	struct acpi_pci_routing_table	*prt = NULL;
-	struct acpi_pci_routing_table	*entry = NULL;
-	static int			first_time = 1;
+	static int		first_time = 1;
+	struct acpi_prt_ref	*entry = NULL;
+	struct acpi_buffer	buffer = {0, NULL};
+	char			pathname[ACPI_PATHNAME_MAX] = {0};
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_add_prt");
 
 	if (first_time) {
-		acpi_prt.count = 0;
-		INIT_LIST_HEAD(&acpi_prt.entries);
+		acpi_prt_ref_list.count = 0;
+		INIT_LIST_HEAD(&acpi_prt_ref_list.entries);
 		first_time = 0;
 	}
 
+   
 	/* 
 	 * NOTE: We're given a 'handle' to the _PRT object's parent device
 	 *       (either a PCI root bridge or PCI-PCI bridge).
@@ -189,42 +314,19 @@
 	printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
 		pathname);
 
-	/* 
-	 * Evaluate this _PRT and add its entries to our global list (acpi_prt).
-	 */
-
-	buffer.length = 0;
-	buffer.pointer = NULL;
-	status = acpi_get_irq_routing_table(handle, &buffer);
-	if (status != AE_BUFFER_OVERFLOW) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
-			acpi_format_exception(status)));
-		return_VALUE(-ENODEV);
-	}
-
-	prt = kmalloc(buffer.length, GFP_KERNEL);
-	if (!prt)
+   
+   
+	entry = kmalloc(sizeof(struct acpi_prt_ref), GFP_KERNEL);
+	if (!entry)
 		return_VALUE(-ENOMEM);
-	memset(prt, 0, buffer.length);
-	buffer.pointer = prt;
-
-	status = acpi_get_irq_routing_table(handle, &buffer);
-	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n",
-			acpi_format_exception(status)));
-		kfree(buffer.pointer);
-		return_VALUE(-ENODEV);
-	}
-
-	entry = prt;
-
-	while (entry && (entry->length > 0)) {
-		acpi_pci_irq_add_entry(handle, segment, bus, entry);
-		entry = (struct acpi_pci_routing_table *)
-			((unsigned long) entry + entry->length);
-	}
+	memset(entry, 0, sizeof(struct acpi_prt_ref));
+   
+	entry->handle = handle;
+	entry->segment = segment;
+	entry->bus = bus;
 
-	kfree(prt);
+	list_add_tail(&entry->node, &acpi_prt_ref_list.entries);
+	acpi_prt_ref_list.count++;
 
 	return_VALUE(0);
 }
@@ -383,6 +485,14 @@
 	return_VALUE(dev->irq);
 }
 
+static void __init acpi_irq_pic_mode(void)
+{
+	acpi_irq_model = ACPI_IRQ_MODEL_PIC;
+	acpi_bus_init_irq();
+   
+        /* recalculate penalties */
+ 	acpi_pci_link_calc_penalties();
+}
 
 int __init
 acpi_pci_irq_init (void)
@@ -391,27 +501,27 @@
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_init");
 
-	if (!acpi_prt.count) {
-		printk(KERN_WARNING PREFIX "ACPI tables contain no PCI IRQ "
-			"routing entries\n");
-		return_VALUE(-ENODEV);
-	}
 
-	/* Make sure all link devices have a valid IRQ. */
-	if (acpi_pci_link_check()) {
-		return_VALUE(-ENODEV);
-	}
+ 	/* Calculate IRQ penalties for each link device */
+ 	acpi_pci_link_calc_penalties();
 
 #ifdef CONFIG_X86_IO_APIC
 	/* Program IOAPICs using data from PRT entries. */
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-		mp_parse_prt();
+ 		if (mp_parse_prt()) 
+ 			acpi_irq_pic_mode();
 #endif
 #ifdef CONFIG_IOSAPIC
 	if (acpi_irq_model == ACPI_IRQ_MODEL_IOSAPIC)
-		iosapic_parse_prt();
+ 		if (iosapic_parse_prt())
+			return_VALUE(-ENODEV);
 #endif
-
+   
+ 	/* This one is last, as a catchall */
+ 	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC)
+ 		if (pic_parse_prt()) 
+ 			return_VALUE(-ENODEV);
+   
 	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
 		acpi_pci_irq_enable(dev);
 
--- linux-2.6.0-test4.orig/drivers/acpi/pci_link.c	2003-08-23 00:52:08.000000000 +0100
+++ linux-2.6.0-test4.picmode/drivers/acpi/pci_link.c	2003-09-06 00:24:06.666213344 +0100
@@ -279,7 +279,6 @@
 	return_VALUE(result);
 }
 
-
 static int
 acpi_pci_link_set (
 	struct acpi_pci_link	*link,
@@ -316,13 +315,13 @@
 			return_VALUE(-EINVAL);
 		}
 	}
-
+   
 	memset(&resource, 0, sizeof(resource));
 
 	/* NOTE: PCI interrupts are always level / active_low / shared. But not all
 	   interrupts > 15 are PCI interrupts. Rely on the ACPI IRQ definition for 
 	   parameters */
-	if (irq <= 15) {
+	if (irq <= 15) {	
 		resource.res.id = ACPI_RSTYPE_IRQ;
 		resource.res.length = sizeof(struct acpi_resource);
 		resource.res.data.irq.edge_level = link->irq.edge_level;
@@ -401,23 +400,26 @@
  * as 'best bets' for PCI use.
  */
 
-static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
+static int acpi_irq_default_penalty[ACPI_MAX_IRQS] = {
 	1000000,  1000000,  1000000,    10000, 
 	  10000,        0,    10000,    10000,
 	  10000,        0,        0,        0, 
 	  10000,   100000,   100000,   100000,
 };
 
+static int acpi_irq_penalty[ACPI_MAX_IRQS] = { 0 };
 
 int
-acpi_pci_link_check (void)
+acpi_pci_link_calc_penalties (void)
 {
 	struct list_head	*node = NULL;
 	struct acpi_pci_link    *link = NULL;
 	int			i = 0;
 
-	ACPI_FUNCTION_TRACE("acpi_pci_link_check");
+	ACPI_FUNCTION_TRACE("acpi_pci_link_calc_penalties");
 
+	memcpy(&acpi_irq_penalty, &acpi_irq_default_penalty, sizeof(acpi_irq_default_penalty));
+   
 	/*
 	 * Update penalties to facilitate IRQ balancing.
 	 */
@@ -428,6 +430,7 @@
 			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
 			continue;
 		}
+		link->irq.setonboot = 0;
 
 		if (link->irq.active)
 			acpi_irq_penalty[link->irq.active] += 100;
@@ -458,18 +461,18 @@
 		irq = link->irq.possible[0];
 	}
 
-		/* 
-		 * Select the best IRQ.  This is done in reverse to promote 
-		 * the use of IRQs 9, 10, 11, and >15.
-		 */
-		for (i=(link->irq.possible_count-1); i>0; i--) {
-			if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
-				irq = link->irq.possible[i];
-		}
+	/* 
+	 * Select the best IRQ.  This is done in reverse to promote 
+	 * the use of IRQs 9, 10, 11, and >15.
+	 */
+	for (i=(link->irq.possible_count-1); i>0; i--) {
+		if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
+			irq = link->irq.possible[i];
+	}
 
 	/* Attempt to enable the link device at this IRQ. */
 	if (acpi_pci_link_set(link, irq)) {
-		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",
+		printk(PREFIX "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS, please report to acpi-devel!)\n",
 			acpi_device_name(link->device),
 			acpi_device_bid(link->device));
 		return_VALUE(-ENODEV);
--- linux-2.6.0-test4.orig/drivers/acpi/bus.c	2003-08-23 00:57:08.000000000 +0100
+++ linux-2.6.0-test4.picmode/drivers/acpi/bus.c	2003-09-06 00:20:15.843303760 +0100
@@ -536,7 +536,7 @@
                              Initialization/Cleanup
    -------------------------------------------------------------------------- */
 
-static int __init
+int
 acpi_bus_init_irq (void)
 {
 	acpi_status		status = AE_OK;
--- linux-2.6.0-test4.orig/include/acpi/acpi_drivers.h	2003-08-23 00:58:03.000000000 +0100
+++ linux-2.6.0-test4.picmode/include/acpi/acpi_drivers.h	2003-09-06 00:20:15.843303760 +0100
@@ -26,6 +26,9 @@
 #ifndef __ACPI_DRIVERS_H__
 #define __ACPI_DRIVERS_H__
 
+/* forward definitions */
+struct acpi_prt_list;
+
 #include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
 
@@ -59,12 +62,15 @@
 
 /* ACPI PCI Interrupt Link (pci_link.c) */
 
-int acpi_pci_link_check (void);
+int acpi_pci_link_calc_penalties (void);
 int acpi_pci_link_get_irq (acpi_handle handle, int index, int* edge_level, int* active_high_low);
 
 /* ACPI PCI Interrupt Routing (pci_irq.c) */
 
 int acpi_pci_irq_add_prt (acpi_handle handle, int segment, int bus);
+int acpi_pci_commit_prt_list (struct acpi_prt_list* prt_list);
+int acpi_pci_destroy_prt_list (struct acpi_prt_list* prt_list);
+struct acpi_prt_list* acpi_pci_get_prt_list (void);
 
 /* ACPI PCI Device Binding (pci_bind.c) */
 
--- linux-2.6.0-test4.orig/include/linux/acpi.h	2003-08-23 00:50:23.000000000 +0100
+++ linux-2.6.0-test4.picmode/include/linux/acpi.h	2003-09-06 00:20:15.844303608 +0100
@@ -399,7 +399,7 @@
 	struct list_head	entries;
 };
 
-extern struct acpi_prt_list	acpi_prt;
+extern struct acpi_prt_list*	acpi_prt;
 
 struct pci_dev;
 
--- linux-2.6.0-test4.orig/include/acpi/acpi_bus.h	2003-08-23 00:54:33.000000000 +0100
+++ linux-2.6.0-test4.picmode/include/acpi/acpi_bus.h	2003-09-06 00:20:15.844303608 +0100
@@ -308,6 +308,8 @@
 int acpi_create_dir(struct acpi_device *);
 void acpi_remove_dir(struct acpi_device *);
 
+int acpi_bus_init_irq (void);
+
 #endif /*CONFIG_ACPI_BUS*/
 
 #endif /*__ACPI_BUS_H__*/


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH] 2.6.0-test4 ACPI fixes series (2/4)
  2003-09-05 22:28     ` Jeff Garzik
                         ` (4 preceding siblings ...)
  2003-09-06  0:57       ` [PATCH] 2.6.0-test4 ACPI fixes series (1/4) Andrew de Quincey
@ 2003-09-06  0:57       ` Andrew de Quincey
  2003-09-06  0:57       ` [PATCH] 2.6.0-test4 ACPI fixes series (3/4) Andrew de Quincey
  2003-09-06  0:57       ` [PATCH] 2.6.0-test4 ACPI fixes series (4/4) Andrew de Quincey
  7 siblings, 0 replies; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-06  0:57 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: torvalds, lkml, acpi-devel, linux-acpi

This patch retries IRQ programming with an extended IRQ resource descriptor
if using a standard IRQ descriptor fails.


--- linux-2.6.0-test4.picmode/drivers/acpi/pci_link.c	2003-09-06 00:24:06.666213344 +0100
+++ linux-2.6.0-test4.extirq/drivers/acpi/pci_link.c	2003-09-06 00:26:18.912108912 +0100
@@ -293,7 +293,8 @@
 	struct acpi_buffer	buffer = {sizeof(resource)+1, &resource};
 	int			i = 0;
 	int			valid = 0;
-
+	int			resource_type = 0;
+   
 	ACPI_FUNCTION_TRACE("acpi_pci_link_set");
 
 	if (!link || !irq)
@@ -315,21 +316,33 @@
 			return_VALUE(-EINVAL);
 		}
 	}
+
+	/* If IRQ<=15, first try with a "normal" IRQ descriptor. If that fails, try with
+	 * an extended one */
+	if (irq <= 15) {
+		resource_type = ACPI_RSTYPE_IRQ;
+	} else {
+		resource_type = ACPI_RSTYPE_EXT_IRQ;
+	}
+
+retry_programming:
    
 	memset(&resource, 0, sizeof(resource));
 
 	/* NOTE: PCI interrupts are always level / active_low / shared. But not all
 	   interrupts > 15 are PCI interrupts. Rely on the ACPI IRQ definition for 
 	   parameters */
-	if (irq <= 15) {	
+	switch(resource_type) {
+	case ACPI_RSTYPE_IRQ:
 		resource.res.id = ACPI_RSTYPE_IRQ;
 		resource.res.length = sizeof(struct acpi_resource);
 		resource.res.data.irq.edge_level = link->irq.edge_level;
 		resource.res.data.irq.active_high_low = link->irq.active_high_low;
 		resource.res.data.irq.number_of_interrupts = 1;
 		resource.res.data.irq.interrupts[0] = irq;
-	}
-	else {
+		break;
+	   
+	case ACPI_RSTYPE_EXT_IRQ:
 		resource.res.id = ACPI_RSTYPE_EXT_IRQ;
 		resource.res.length = sizeof(struct acpi_resource);
 		resource.res.data.extended_irq.producer_consumer = ACPI_CONSUMER;
@@ -338,11 +351,22 @@
 		resource.res.data.extended_irq.number_of_interrupts = 1;
 		resource.res.data.extended_irq.interrupts[0] = irq;
 		/* ignore resource_source, it's optional */
+		break;
 	}
 	resource.end.id = ACPI_RSTYPE_END_TAG;
 
 	/* Attempt to set the resource */
 	status = acpi_set_current_resources(link->handle, &buffer);
+   
+
+	/* if we failed and IRQ <= 15, try again with an extended descriptor */
+	if (ACPI_FAILURE(status) && (resource_type == ACPI_RSTYPE_IRQ)) {
+                resource_type = ACPI_RSTYPE_EXT_IRQ;
+                printk(PREFIX "Retrying with extended IRQ descriptor\n");
+                goto retry_programming;
+	}
+  
+	/* check for total failure */
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n"));
 		return_VALUE(-ENODEV);


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH] 2.6.0-test4 ACPI fixes series (3/4)
  2003-09-05 22:28     ` Jeff Garzik
                         ` (5 preceding siblings ...)
  2003-09-06  0:57       ` [PATCH] 2.6.0-test4 ACPI fixes series (2/4) Andrew de Quincey
@ 2003-09-06  0:57       ` Andrew de Quincey
  2003-09-06  0:57       ` [PATCH] 2.6.0-test4 ACPI fixes series (4/4) Andrew de Quincey
  7 siblings, 0 replies; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-06  0:57 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: torvalds, lkml, acpi-devel, linux-acpi

This patch is actually a patch by "Jun Nakajima" <jun.nakajima@intel.com>
When setting an IRQ link device, it checks if the value returned by _CRS is
0. If so, it assumes everything went OK. This fixes problems on MANY VIA
bioses. It seems to be a standard-ish way of saying "the _CRS IRQ setting
cannot be read".


--- linux-2.4.23-pre3.extirq/drivers/acpi/pci_link.c	2003-09-05 23:54:59.945755216 +0100
+++ linux-2.4.23-pre3.null_crs/drivers/acpi/pci_link.c	2003-09-05 23:57:39.782456344 +0100
@@ -277,6 +277,32 @@
 
 
 static int
+acpi_pci_link_try_get_current (
+	struct acpi_pci_link *link,
+	int irq)
+{
+	int result;
+
+	ACPI_FUNCTION_TRACE("acpi_pci_link_try_get_current");
+   
+	result = acpi_pci_link_get_current(link);
+	if (result && link->irq.active) 
+	{
+		return_VALUE(result);
+	}
+
+	if (!link->irq.active) 
+	{
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No active IRQ resource found\n"));
+		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));
+		link->irq.active = irq;
+	}
+   
+	return 0;
+}
+
+
+static int
 acpi_pci_link_set (
 	struct acpi_pci_link	*link,
 	int			irq)
@@ -382,7 +408,7 @@
 	}
 
 	/* Make sure the active IRQ is the one we requested. */
-	result = acpi_pci_link_get_current(link);
+	result = acpi_pci_link_try_get_current(link, irq);
 	if (result) {
 		return_VALUE(result);
 	}
@@ -600,10 +626,6 @@
 		else
 			printk(" %d", link->irq.possible[i]);
 	}
-	if (!link->irq.active)
-		printk(", disabled");
-	else if (!found)
-		printk(", enabled at IRQ %d", link->irq.active);
 	printk(")\n");
 
 	/* TBD: Acquire/release lock */


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH] 2.6.0-test4 ACPI fixes series (4/4)
  2003-09-05 22:28     ` Jeff Garzik
                         ` (6 preceding siblings ...)
  2003-09-06  0:57       ` [PATCH] 2.6.0-test4 ACPI fixes series (3/4) Andrew de Quincey
@ 2003-09-06  0:57       ` Andrew de Quincey
  2003-09-06  1:22         ` Jeff Garzik
  2003-09-06 15:47         ` [ACPI] " Alan Cox
  7 siblings, 2 replies; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-06  0:57 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: torvalds, lkml, acpi-devel, linux-acpi

This patch removes some erroneous code from mpparse which breaks IO-APIC programming


--- linux-2.6.0-test4.null_crs/arch/i386/kernel/mpparse.c	2003-09-06 00:23:10.000000000 +0100
+++ linux-2.6.0-test4.duffmpparse/arch/i386/kernel/mpparse.c	2003-09-06 00:28:23.788124872 +0100
@@ -1129,9 +1129,6 @@
 			continue;
 		ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start;
 
-		if (!ioapic && (irq < 16))
-			irq += 16;
-
 		/* 
 		 * Avoid pin reprogramming.  PRTs typically include entries  
 		 * with redundant pin->irq mappings (but unique PCI devices);


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed)
  2003-09-06  0:02     ` [ACPI] Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed) Chris Wright
@ 2003-09-06  1:21       ` Andrew de Quincey
  2003-09-06  0:30         ` Jeff Garzik
  0 siblings, 1 reply; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-06  1:21 UTC (permalink / raw)
  To: Chris Wright; +Cc: lkml, acpi-devel

On Saturday 06 Sep 2003 1:02 am, Chris Wright wrote:
> * Andrew de Quincey (adq_dvb@lidskialf.net) wrote:
> > On Friday 05 Sep 2003 10:35 pm, Jeff Garzik wrote:
> > > This is why we _really_ need you to split up your patches.  Multiple
> > > split-up patches, one per email, is preferred.  Don't worry about
> > > sending us too much email:  we like it like that.
> >
> > If/when I split it up, is it acceptable to number the patches to give the
> > order they have to be applied in? The major problem with these particular
> > fixes is that they all run over the same set of files, even the same
> > functions, so they all conflict with each other.
>
> Yes, please split them up.
>
> I finally narrowed down to the ChangeSet 1.1046.1.424 (ACPI: Allow irqs >
> 15...) as cause to my current hang-on-boot problem.  Quick test to see
> if this patch fixes...nope ;-(

I have reports of a number of systems with issues like this. 

I have a machine here (A Fujitsu Siemens TX150 server) in which the SCSI 
controller actually corrupts the low level format of the hard disk if I 
enable ACPI! (low level reformat required!). The ACPI IRQ setup seems to work 
fine on it (as I assume it does on your system). Its just that there seems to 
be "something else" wrong in ACPI still. Weirdly enough, it can read sector 0 
of the HDD fine.. just any reads of any other sectors cause this corruption.

Now that I've got the bulk of the changes to the basic ACPI IRQ setup done, I 
can concentrate on these issues. Can you give me details of your system and 
the following items:

successful dmesg
dmesg from a failed boot
/proc/acpi/dsdt
/proc/interrupts


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] 2.6.0-test4 ACPI fixes series (4/4)
  2003-09-06  0:57       ` [PATCH] 2.6.0-test4 ACPI fixes series (4/4) Andrew de Quincey
@ 2003-09-06  1:22         ` Jeff Garzik
  2003-09-06 12:27           ` [ACPI] " Andrew de Quincey
  2003-09-08 19:46           ` Mikael Pettersson
  2003-09-06 15:47         ` [ACPI] " Alan Cox
  1 sibling, 2 replies; 30+ messages in thread
From: Jeff Garzik @ 2003-09-06  1:22 UTC (permalink / raw)
  To: Andrew de Quincey
  Cc: torvalds, lkml, acpi-devel, linux-acpi, Mikael Pettersson

Andrew de Quincey wrote:
> This patch removes some erroneous code from mpparse which breaks IO-APIC programming
> 
> 
> --- linux-2.6.0-test4.null_crs/arch/i386/kernel/mpparse.c	2003-09-06 00:23:10.000000000 +0100
> +++ linux-2.6.0-test4.duffmpparse/arch/i386/kernel/mpparse.c	2003-09-06 00:28:23.788124872 +0100
> @@ -1129,9 +1129,6 @@
>  			continue;
>  		ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start;
>  
> -		if (!ioapic && (irq < 16))
> -			irq += 16;
> -


Even though I've been digging through stuff off and on, I consider 
myself pretty darn IOAPIC-clueless.  Mikael, does this look sane to you?


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed)
  2003-09-06  0:30         ` Jeff Garzik
@ 2003-09-06  2:03           ` Chris Wright
  2003-09-06 12:32             ` Andrew de Quincey
  0 siblings, 1 reply; 30+ messages in thread
From: Chris Wright @ 2003-09-06  2:03 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Andrew de Quincey, Chris Wright, lkml, acpi-devel

* Jeff Garzik (jgarzik@pobox.com) wrote:
> Andrew de Quincey wrote:
> > successful dmesg
> > dmesg from a failed boot
> > /proc/acpi/dsdt
> > /proc/interrupts
> 
> dmidecode output is also quite helpful.

I've uploaded these to:

http://lsm.immunix.org/~chris/acpi/

You'll find dmesg and interrupts from pci=noacpi, acpi=off, disassembled
dsdt and dmidecode.  Don't have the failed boot dmesg yet.  I ported
netconsole to my eth driver, but it's not yet working.

thanks,
-chris
-- 
Linux Security Modules     http://lsm.immunix.org     http://lsm.bkbits.net

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] Re: [PATCH] 2.6.0-test4 ACPI fixes series (4/4)
  2003-09-06  1:22         ` Jeff Garzik
@ 2003-09-06 12:27           ` Andrew de Quincey
  2003-09-06 13:45             ` Andi Kleen
  2003-09-08 19:46           ` Mikael Pettersson
  1 sibling, 1 reply; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-06 12:27 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: torvalds, lkml, acpi-devel, linux-acpi, Mikael Pettersson

On Saturday 06 September 2003 02:22, Jeff Garzik wrote:
> Andrew de Quincey wrote:
> > This patch removes some erroneous code from mpparse which breaks IO-APIC
> > programming
> >
> >
> > --- linux-2.6.0-test4.null_crs/arch/i386/kernel/mpparse.c	2003-09-06
> > 00:23:10.000000000 +0100 +++
> > linux-2.6.0-test4.duffmpparse/arch/i386/kernel/mpparse.c	2003-09-06
> > 00:28:23.788124872 +0100 @@ -1129,9 +1129,6 @@
> >  			continue;
> >  		ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start;
> >
> > -		if (!ioapic && (irq < 16))
> > -			irq += 16;
> > -
>
> Even though I've been digging through stuff off and on, I consider
> myself pretty darn IOAPIC-clueless.  Mikael, does this look sane to you?

Really breaks on TX150 servers... All IRQs < 16 get +16 added onto them, which 
breaks all IRQ routing. It's also already been removed from 2.4.23-pre3


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed)
  2003-09-06  2:03           ` Chris Wright
@ 2003-09-06 12:32             ` Andrew de Quincey
  2003-09-11  1:36               ` Chris Wright
  0 siblings, 1 reply; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-06 12:32 UTC (permalink / raw)
  To: Chris Wright, Jeff Garzik; +Cc: Chris Wright, lkml, acpi-devel

On Saturday 06 September 2003 03:03, Chris Wright wrote:
> * Jeff Garzik (jgarzik@pobox.com) wrote:
> > Andrew de Quincey wrote:
> > > successful dmesg
> > > dmesg from a failed boot
> > > /proc/acpi/dsdt
> > > /proc/interrupts
> >
> > dmidecode output is also quite helpful.
>
> I've uploaded these to:
>
> http://lsm.immunix.org/~chris/acpi/
>
> You'll find dmesg and interrupts from pci=noacpi, acpi=off, disassembled
> dsdt and dmidecode.  Don't have the failed boot dmesg yet.  I ported
> netconsole to my eth driver, but it's not yet working.

Cool, ta.. I'll have a look, but I'll probably need the failed dmesg to make 
any real progress.


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] Re: [PATCH] 2.6.0-test4 ACPI fixes series (4/4)
  2003-09-06 12:27           ` [ACPI] " Andrew de Quincey
@ 2003-09-06 13:45             ` Andi Kleen
  0 siblings, 0 replies; 30+ messages in thread
From: Andi Kleen @ 2003-09-06 13:45 UTC (permalink / raw)
  To: Andrew de Quincey
  Cc: jgarzik, torvalds, linux-kernel, acpi-devel, linux-acpi, mikpe

On Sat, 6 Sep 2003 13:27:16 +0100
Andrew de Quincey <adq_dvb@lidskialf.net> wrote:

> On Saturday 06 September 2003 02:22, Jeff Garzik wrote:
> > Andrew de Quincey wrote:
> > > This patch removes some erroneous code from mpparse which breaks IO-APIC
> > > programming
> > >
> > >
> > > --- linux-2.6.0-test4.null_crs/arch/i386/kernel/mpparse.c	2003-09-06
> > > 00:23:10.000000000 +0100 +++
> > > linux-2.6.0-test4.duffmpparse/arch/i386/kernel/mpparse.c	2003-09-06
> > > 00:28:23.788124872 +0100 @@ -1129,9 +1129,6 @@
> > >  			continue;
> > >  		ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start;
> > >
> > > -		if (!ioapic && (irq < 16))
> > > -			irq += 16;
> > > -
> >
> > Even though I've been digging through stuff off and on, I consider
> > myself pretty darn IOAPIC-clueless.  Mikael, does this look sane to you?
> 
> Really breaks on TX150 servers... All IRQs < 16 get +16 added onto them, which 
> breaks all IRQ routing. It's also already been removed from 2.4.23-pre3

It is needed at least for the Unisys ES7000. But that box needs further changes
anyways which are not in tree yet and is even an own subarchitecture that can be 
tested for.

-Andi

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] [PATCH] 2.6.0-test4 ACPI fixes series (4/4)
  2003-09-06  0:57       ` [PATCH] 2.6.0-test4 ACPI fixes series (4/4) Andrew de Quincey
  2003-09-06  1:22         ` Jeff Garzik
@ 2003-09-06 15:47         ` Alan Cox
  2003-09-07 14:54           ` Andrew de Quincey
  1 sibling, 1 reply; 30+ messages in thread
From: Alan Cox @ 2003-09-06 15:47 UTC (permalink / raw)
  To: Andrew de Quincey; +Cc: Jeff Garzik, torvalds, lkml, acpi-devel, linux-acpi

On Sad, 2003-09-06 at 01:57, Andrew de Quincey wrote:
> This patch removes some erroneous code from mpparse which breaks IO-APIC programming

These shouldnt be removed but checked against the arch being an E7000,
which does need this.


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] [PATCH] 2.6.0-test4 ACPI fixes series (4/4)
  2003-09-06 15:47         ` [ACPI] " Alan Cox
@ 2003-09-07 14:54           ` Andrew de Quincey
  2003-09-07 17:59             ` Alan Cox
  0 siblings, 1 reply; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-07 14:54 UTC (permalink / raw)
  To: Alan Cox; +Cc: Jeff Garzik, torvalds, lkml, acpi-devel, linux-acpi

On Saturday 06 September 2003 16:47, Alan Cox wrote:
> On Sad, 2003-09-06 at 01:57, Andrew de Quincey wrote:
> > This patch removes some erroneous code from mpparse which breaks IO-APIC
> > programming
>
> These shouldnt be removed but checked against the arch being an E7000,
> which does need this.

Should that code be added back into 2.4.23-pre3? 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] [PATCH] 2.6.0-test4 ACPI fixes series (4/4)
  2003-09-07 14:54           ` Andrew de Quincey
@ 2003-09-07 17:59             ` Alan Cox
  2003-09-07 20:19               ` Andrew de Quincey
  0 siblings, 1 reply; 30+ messages in thread
From: Alan Cox @ 2003-09-07 17:59 UTC (permalink / raw)
  To: Andrew de Quincey; +Cc: Jeff Garzik, torvalds, lkml, acpi-devel, linux-acpi

On Sul, 2003-09-07 at 15:54, Andrew de Quincey wrote:
> Should that code be added back into 2.4.23-pre3? 

I dont think E7K ever made it into 2.4


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] [PATCH] 2.6.0-test4 ACPI fixes series (4/4)
  2003-09-07 17:59             ` Alan Cox
@ 2003-09-07 20:19               ` Andrew de Quincey
  0 siblings, 0 replies; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-07 20:19 UTC (permalink / raw)
  To: Alan Cox; +Cc: Jeff Garzik, torvalds, lkml, acpi-devel, linux-acpi

On Sunday 07 Sep 2003 6:59 pm, Alan Cox wrote:
> On Sul, 2003-09-07 at 15:54, Andrew de Quincey wrote:
> > Should that code be added back into 2.4.23-pre3?
>
> I dont think E7K ever made it into 2.4

Oh right, cool. Well that makes fixing that easy then :)


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] 2.6.0-test4 ACPI fixes series (4/4)
  2003-09-06  1:22         ` Jeff Garzik
  2003-09-06 12:27           ` [ACPI] " Andrew de Quincey
@ 2003-09-08 19:46           ` Mikael Pettersson
  1 sibling, 0 replies; 30+ messages in thread
From: Mikael Pettersson @ 2003-09-08 19:46 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Andrew de Quincey, torvalds, lkml, acpi-devel, linux-acpi

Jeff Garzik writes:
 > Andrew de Quincey wrote:
 > > This patch removes some erroneous code from mpparse which breaks IO-APIC programming
 > > 
 > > 
 > > --- linux-2.6.0-test4.null_crs/arch/i386/kernel/mpparse.c	2003-09-06 00:23:10.000000000 +0100
 > > +++ linux-2.6.0-test4.duffmpparse/arch/i386/kernel/mpparse.c	2003-09-06 00:28:23.788124872 +0100
 > > @@ -1129,9 +1129,6 @@
 > >  			continue;
 > >  		ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start;
 > >  
 > > -		if (!ioapic && (irq < 16))
 > > -			irq += 16;
 > > -
 > 
 > 
 > Even though I've been digging through stuff off and on, I consider 
 > myself pretty darn IOAPIC-clueless.  Mikael, does this look sane to you?

Sorry, I'm only a local APIC caretaker, not an I/O-APIC expert.
Check with Alan, Ingo, Maciej, or the big-SMP people.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] 2.4.23-pre3 ACPI fixes series (1/3)
  2003-09-06  0:15       ` [PATCH] 2.4.23-pre3 ACPI fixes series (1/3) Andrew de Quincey
@ 2003-09-10 11:45         ` Bernhard Rosenkraenzer
  2003-09-10 21:27           ` Andrew de Quincey
  2003-09-10 15:31         ` Daniel Egger
  1 sibling, 1 reply; 30+ messages in thread
From: Bernhard Rosenkraenzer @ 2003-09-10 11:45 UTC (permalink / raw)
  To: Andrew de Quincey; +Cc: lkml, acpi-devel, linux-acpi

On Sat, 6 Sep 2003, Andrew de Quincey wrote:

> This patch allows ACPI to drop back to PIC mode if ACPI mode setup fails.

Works nicely here, but causes an oops on startup if you specify acpi=off 
on the command line.

LLaP
bero

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] 2.4.23-pre3 ACPI fixes series (1/3)
  2003-09-06  0:15       ` [PATCH] 2.4.23-pre3 ACPI fixes series (1/3) Andrew de Quincey
  2003-09-10 11:45         ` Bernhard Rosenkraenzer
@ 2003-09-10 15:31         ` Daniel Egger
  1 sibling, 0 replies; 30+ messages in thread
From: Daniel Egger @ 2003-09-10 15:31 UTC (permalink / raw)
  To: Andrew de Quincey; +Cc: Jeff Garzik, torvalds, lkml, acpi-devel, linux-acpi

[-- Attachment #1: Type: text/plain, Size: 925 bytes --]

Am Sam, 2003-09-06 um 02.15 schrieb Andrew de Quincey:

> This patch allows ACPI to drop back to PIC mode if ACPI mode setup fails.

Those patches work miracles for me. Finally I can use my ECS L7VTA with
KT400 chipset with IO-APIC in ACPI mode.

egger@alex:/proc$ cat /proc/interrupts
           CPU0
  0:     119774    IO-APIC-edge  timer
  1:        881    IO-APIC-edge  keyboard
  2:          0          XT-PIC  cascade
  8:          1    IO-APIC-edge  rtc
  9:          0    IO-APIC-edge  acpi
 14:          7    IO-APIC-edge  ide0
 15:         39    IO-APIC-edge  ide1
 16:         57   IO-APIC-level  ohci1394
 17:          0   IO-APIC-level  eth1
 19:          2   IO-APIC-level  ymfpci
 21:          0   IO-APIC-level  usb-uhci, usb-uhci, usb-uhci, ehci_hcd
 23:     253525   IO-APIC-level  eth0
NMI:          0
LOC:     119715
ERR:          0
MIS:          0

-- 
Servus,
       Daniel

[-- Attachment #2: Dies ist ein digital signierter Nachrichtenteil --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] 2.4.23-pre3 ACPI fixes series (1/3)
  2003-09-10 11:45         ` Bernhard Rosenkraenzer
@ 2003-09-10 21:27           ` Andrew de Quincey
  0 siblings, 0 replies; 30+ messages in thread
From: Andrew de Quincey @ 2003-09-10 21:27 UTC (permalink / raw)
  To: Bernhard Rosenkraenzer; +Cc: lkml, acpi-devel, linux-acpi

On Wednesday 10 Sep 2003 12:45 pm, Bernhard Rosenkraenzer wrote:
> On Sat, 6 Sep 2003, Andrew de Quincey wrote:
> > This patch allows ACPI to drop back to PIC mode if ACPI mode setup fails.
>
> Works nicely here, but causes an oops on startup if you specify acpi=off
> on the command line.

Thanks for reporting that. Andi Kleen beat to me patching it.. He posted it to 
LKML and acpi-devel a day or so ago.. 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [ACPI] Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed)
  2003-09-06 12:32             ` Andrew de Quincey
@ 2003-09-11  1:36               ` Chris Wright
  0 siblings, 0 replies; 30+ messages in thread
From: Chris Wright @ 2003-09-11  1:36 UTC (permalink / raw)
  To: Andrew de Quincey; +Cc: Jeff Garzik, lkml, acpi-devel

* Andrew de Quincey (adq_dvb@lidskialf.net) wrote:
> On Saturday 06 September 2003 03:03, Chris Wright wrote:
> > You'll find dmesg and interrupts from pci=noacpi, acpi=off, disassembled
> > dsdt and dmidecode.  Don't have the failed boot dmesg yet.  I ported
> > netconsole to my eth driver, but it's not yet working.
> 
> Cool, ta.. I'll have a look, but I'll probably need the failed dmesg to make 
> any real progress.

Sorry, for the delay.  I captured console output from failed (normal
acpi) boot.  I also re-ran on 2.6.0-test5 and captured those outputs.
The test3-bk3 is actually test3-bk2+acpi_>15_irq.patch which is the
patch that began the breakage for me.

http://developer.osdl.org/chrisw/acpi/2.6.0-test3-bk3/
http://developer.osdl.org/chrisw/acpi/2.6.0-test5/

Each have dmesg and interrupts from pci=noacpi and acpi=off, dmesg with
acpi enabled, disassembled dsdt, and dmidecode.

Let me know if you need any more info.
thanks,
-chris
-- 
Linux Security Modules     http://lsm.immunix.org     http://lsm.bkbits.net

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2003-09-11  1:37 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-09-05 18:58 [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed) Andrew de Quincey
2003-09-05 21:35 ` Jeff Garzik
2003-09-05 23:16   ` [ACPI] " Andrew de Quincey
2003-09-05 22:28     ` Jeff Garzik
2003-09-05 22:28       ` Andrew Morton
2003-09-05 22:56         ` Randy.Dunlap
2003-09-06  0:15       ` [PATCH] 2.4.23-pre3 ACPI fixes series (1/3) Andrew de Quincey
2003-09-10 11:45         ` Bernhard Rosenkraenzer
2003-09-10 21:27           ` Andrew de Quincey
2003-09-10 15:31         ` Daniel Egger
2003-09-06  0:15       ` [PATCH] 2.4.23-pre3 ACPI fixes series (2/3) Andrew de Quincey
2003-09-06  0:15       ` [PATCH] 2.4.23-pre3 ACPI fixes series (3/3) Andrew de Quincey
2003-09-06  0:57       ` [PATCH] 2.6.0-test4 ACPI fixes series (1/4) Andrew de Quincey
2003-09-06  0:57       ` [PATCH] 2.6.0-test4 ACPI fixes series (2/4) Andrew de Quincey
2003-09-06  0:57       ` [PATCH] 2.6.0-test4 ACPI fixes series (3/4) Andrew de Quincey
2003-09-06  0:57       ` [PATCH] 2.6.0-test4 ACPI fixes series (4/4) Andrew de Quincey
2003-09-06  1:22         ` Jeff Garzik
2003-09-06 12:27           ` [ACPI] " Andrew de Quincey
2003-09-06 13:45             ` Andi Kleen
2003-09-08 19:46           ` Mikael Pettersson
2003-09-06 15:47         ` [ACPI] " Alan Cox
2003-09-07 14:54           ` Andrew de Quincey
2003-09-07 17:59             ` Alan Cox
2003-09-07 20:19               ` Andrew de Quincey
2003-09-06  0:02     ` [ACPI] Re: [PATCH] Next round of ACPI IRQ fixes (VIA ACPI fixed) Chris Wright
2003-09-06  1:21       ` Andrew de Quincey
2003-09-06  0:30         ` Jeff Garzik
2003-09-06  2:03           ` Chris Wright
2003-09-06 12:32             ` Andrew de Quincey
2003-09-11  1:36               ` Chris Wright

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).