From: James Cleverdon 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); _