irqchip/omap-intc: Add support for spurious irq handling
Under some conditions, irq sorting procedure used by INTC can go wrong resulting in a spurious irq getting reported. If this condition is not handled, it results in endless stream of: unexpected IRQ trap at vector 00 messages from ack_bad_irq() Handle the spurious interrupt condition in omap-intc driver to prevent this. Measurements using kernel function profiler on AM335x EVM running at 720MHz show that after this patch omap_intc_handle_irq() takes about 37.4us against 34us before this patch. Signed-off-by: Sekhar Nori <nsekhar@ti.com> Acked-by: Tony Lindgren <tony@atomide.com> Cc: John Ogness <john.ogness@linutronix.de> Cc: Felipe Balbi <balbi@ti.com> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Marc Zyngier <marc.zyngier@arm.com> Link: http://lkml.kernel.org/r/9c78a6db02ac55f7af7371b417b6e414d2c3095b.1450188128.git.nsekhar@ti.com Cc: stable@vger.kernel.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
1fd9a71076
commit
d3b421cd07
@ -47,6 +47,7 @@
|
||||
#define INTC_ILR0 0x0100
|
||||
|
||||
#define ACTIVEIRQ_MASK 0x7f /* omap2/3 active interrupt bits */
|
||||
#define SPURIOUSIRQ_MASK (0x1ffffff << 7)
|
||||
#define INTCPS_NR_ILR_REGS 128
|
||||
#define INTCPS_NR_MIR_REGS 4
|
||||
|
||||
@ -329,11 +330,35 @@ static int __init omap_init_irq(u32 base, struct device_node *node)
|
||||
static asmlinkage void __exception_irq_entry
|
||||
omap_intc_handle_irq(struct pt_regs *regs)
|
||||
{
|
||||
extern unsigned long irq_err_count;
|
||||
u32 irqnr;
|
||||
|
||||
irqnr = intc_readl(INTC_SIR);
|
||||
|
||||
/*
|
||||
* A spurious IRQ can result if interrupt that triggered the
|
||||
* sorting is no longer active during the sorting (10 INTC
|
||||
* functional clock cycles after interrupt assertion). Or a
|
||||
* change in interrupt mask affected the result during sorting
|
||||
* time. There is no special handling required except ignoring
|
||||
* the SIR register value just read and retrying.
|
||||
* See section 6.2.5 of AM335x TRM Literature Number: SPRUH73K
|
||||
*
|
||||
* Many a times, a spurious interrupt situation has been fixed
|
||||
* by adding a flush for the posted write acking the IRQ in
|
||||
* the device driver. Typically, this is going be the device
|
||||
* driver whose interrupt was handled just before the spurious
|
||||
* IRQ occurred. Pay attention to those device drivers if you
|
||||
* run into hitting the spurious IRQ condition below.
|
||||
*/
|
||||
if (unlikely((irqnr & SPURIOUSIRQ_MASK) == SPURIOUSIRQ_MASK)) {
|
||||
pr_err_once("%s: spurious irq!\n", __func__);
|
||||
irq_err_count++;
|
||||
omap_ack_irq(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
irqnr &= ACTIVEIRQ_MASK;
|
||||
WARN_ONCE(!irqnr, "Spurious IRQ ?\n");
|
||||
handle_domain_irq(domain, irqnr, regs);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user