Commit 6906cc82 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Add slow path lookup in xics_get_irq

From: Jake Moilanen <moilanen@austin.ibm.com>

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).
parent 93524205
......@@ -910,4 +910,37 @@ int virt_irq_create_mapping(unsigned int real_irq)
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
......@@ -327,6 +327,8 @@ static void xics_mask_and_ack_irq(unsigned int irq)
}
}
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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment