From: Jake Moilanen In xics_get_irq(), for a real-to-virt irq lookup, go down the slowpath by looking through the entire virt_irq_to_real_map array if take a miss on the radix tree. This is possible, when an interrupt is taken before the driver has called request_irq() (eg IDE). --- 25-akpm/arch/ppc64/kernel/irq.c | 33 +++++++++++++++++++++++++++++++++ 25-akpm/arch/ppc64/kernel/xics.c | 4 ++++ 2 files changed, 37 insertions(+) diff -puN arch/ppc64/kernel/irq.c~ppc64-ide_request_irq arch/ppc64/kernel/irq.c --- 25/arch/ppc64/kernel/irq.c~ppc64-ide_request_irq 2004-03-14 15:35:09.508493072 -0800 +++ 25-akpm/arch/ppc64/kernel/irq.c 2004-03-14 15:35:09.511492616 -0800 @@ -910,4 +910,37 @@ int virt_irq_create_mapping(unsigned int return NO_IRQ; } +/* + * In most cases will get a hit on the very first slot checked in the + * virt_irq_to_real_map. Only when there are a large number of + * IRQs will this be expensive. + */ +unsigned int real_irq_to_virt_slowpath(unsigned int real_irq) +{ + unsigned int virq; + unsigned int first_virq; + + virq = real_irq; + + if (virq > MAX_VIRT_IRQ) + virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ; + + first_virq = virq; + + do { + if (virt_irq_to_real_map[virq] == real_irq) + return virq; + + virq++; + + if (virq >= MAX_VIRT_IRQ) + virq = 0; + + } while (first_virq != virq); + + return NO_IRQ; + +} + + #endif diff -puN arch/ppc64/kernel/xics.c~ppc64-ide_request_irq arch/ppc64/kernel/xics.c --- 25/arch/ppc64/kernel/xics.c~ppc64-ide_request_irq 2004-03-14 15:35:09.509492920 -0800 +++ 25-akpm/arch/ppc64/kernel/xics.c 2004-03-14 15:35:09.512492464 -0800 @@ -327,6 +327,8 @@ static void xics_mask_and_ack_irq(unsign } } +extern unsigned int real_irq_to_virt_slowpath(unsigned int real_irq); + int xics_get_irq(struct pt_regs *regs) { unsigned int cpu = smp_processor_id(); @@ -349,6 +351,8 @@ int xics_get_irq(struct pt_regs *regs) irq = -1; } else { irq = real_irq_to_virt(vec); + if (irq == NO_IRQ) + irq = real_irq_to_virt_slowpath(vec); if (irq == NO_IRQ) { printk(KERN_ERR "Interrupt 0x%x (real) is invalid," " disabling it.\n", vec); _