From: James Cleverdon <jamesclv@us.ibm.com>

irq_vector is indexed by a value that can be as large as the sum of all the
RTEs in all the I/O APICs.  On a 32-way x445 or a 16-way x440 with PCI
expansion boxes, the static array will overflow.

Type changed to u8 because that's how big a vector number is.  That should
please the embedded folks.

Because the fixmaps for I/O APICs aren't ready, I had to map them myself.



 arch/i386/kernel/io_apic.c |    5 +++--
 arch/i386/kernel/mpparse.c |   28 ++++++++++++++++++++++++++++
 include/asm-i386/hw_irq.h  |    5 +++--
 3 files changed, 34 insertions(+), 4 deletions(-)

diff -puN arch/i386/kernel/io_apic.c~dynamic-irq_vector-allocation arch/i386/kernel/io_apic.c
--- 25/arch/i386/kernel/io_apic.c~dynamic-irq_vector-allocation	2003-10-04 00:38:24.000000000 -0700
+++ 25-akpm/arch/i386/kernel/io_apic.c	2003-10-04 00:39:03.000000000 -0700
@@ -1144,13 +1144,14 @@ static inline int IO_APIC_irq_trigger(in
 	return 0;
 }
 
-int irq_vector[NR_IRQS] = { FIRST_DEVICE_VECTOR , 0 };
+u8 *irq_vector;
+int nr_irqs;
 
 #ifndef CONFIG_PCI_USE_VECTOR
 int __init assign_irq_vector(int irq)
 {
 	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
-	BUG_ON(irq >= NR_IRQS);
+	BUG_ON(irq >= nr_irqs);
 	if (IO_APIC_VECTOR(irq) > 0)
 		return IO_APIC_VECTOR(irq);
 next:
diff -puN arch/i386/kernel/mpparse.c~dynamic-irq_vector-allocation arch/i386/kernel/mpparse.c
--- 25/arch/i386/kernel/mpparse.c~dynamic-irq_vector-allocation	2003-10-04 00:38:24.000000000 -0700
+++ 25-akpm/arch/i386/kernel/mpparse.c	2003-10-04 00:38:24.000000000 -0700
@@ -616,6 +616,31 @@ static inline void __init construct_defa
 	}
 }
 
+#ifdef CONFIG_X86_IO_APIC
+/* irq_vector must be have an entry for all RTEs of all I/O APICs. */
+void __init alloc_irq_vector_array(void)
+{
+	int	total = 0;
+	int	idx;
+	union IO_APIC_reg_01	reg_01;
+
+	/* The I/O APIC fixmaps aren't inited yet, so use the first one. */
+	for (idx = 0; idx < nr_ioapics; idx++) {
+		set_fixmap_nocache(FIX_IO_APIC_BASE_0, mp_ioapics[idx].mpc_apicaddr);
+		reg_01.raw = io_apic_read(0, 1);
+		total += reg_01.bits.entries + 1;
+	}
+
+	/* Always alloc at least NR_IRQS vectors. */
+	nr_irqs = max(total, NR_IRQS);
+	irq_vector = (u8 *) alloc_bootmem(nr_irqs);
+	memset(irq_vector, 0, nr_irqs);
+	irq_vector[0] = FIRST_DEVICE_VECTOR;
+}
+#else
+void __init alloc_irq_vector_array(void) { }
+#endif /* CONFIG_X86_IO_APIC */
+
 static struct intel_mp_floating *mpf_found;
 
 /*
@@ -633,6 +658,7 @@ void __init get_smp_config (void)
 	 */
 	if (acpi_lapic && acpi_ioapic) {
 		printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");
+		alloc_irq_vector_array();
 		return;
 	}
 	else if (acpi_lapic)
@@ -665,6 +691,7 @@ void __init get_smp_config (void)
 			smp_found_config = 0;
 			printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");
 			printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");
+			alloc_irq_vector_array();
 			return;
 		}
 		/*
@@ -688,6 +715,7 @@ void __init get_smp_config (void)
 	} else
 		BUG();
 
+	alloc_irq_vector_array();
 	printk(KERN_INFO "Processors: %d\n", num_processors);
 	/*
 	 * Only use the first configuration found.
diff -puN include/asm-i386/hw_irq.h~dynamic-irq_vector-allocation include/asm-i386/hw_irq.h
--- 25/include/asm-i386/hw_irq.h~dynamic-irq_vector-allocation	2003-10-04 00:38:24.000000000 -0700
+++ 25-akpm/include/asm-i386/hw_irq.h	2003-10-04 00:38:24.000000000 -0700
@@ -25,8 +25,9 @@
  * Interrupt entry/exit code at both C and assembly level
  */
 
-extern int irq_vector[NR_IRQS];
-#define IO_APIC_VECTOR(irq)	irq_vector[irq]
+extern u8 *irq_vector;
+#define IO_APIC_VECTOR(irq)	((int)irq_vector[(irq)])
+extern int nr_irqs;
 
 extern void (*interrupt[NR_IRQS])(void);
 

_