diff options
author | Stefan Sørensen <stefan.sorensen@spectralink.com> | 2014-03-06 10:27:15 -0500 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2014-03-13 16:34:48 -0400 |
commit | 698b48532539484b012fb7c4176b959d32a17d00 (patch) | |
tree | 4d91b13bddccc7fe209907fe25c72161b089d40b /arch | |
parent | cfbf8d4857c26a8a307fb7cd258074c9dcd8c691 (diff) |
ARM: OMAP2+: INTC: Acknowledge stuck active interrupts
When an interrupt has become active on the INTC it will stay active
until it is acked, even if masked or de-asserted. The
INTC_PENDING_IRQn registers are however updated and since these are
used by omap_intc_handle_irq to determine which interrupt to handle,
it will never see the active interrupt. This will result in a storm of
useless interrupts that is only stopped when another higher priority
interrupt is asserted.
Fix by sending the INTC an acknowledge if we find no interrupts to
handle.
Cc: stable@vger.kernel.org
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-omap2/irq.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index e022a869bff2..6037a9a01ed5 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c | |||
@@ -222,6 +222,7 @@ void __init ti81xx_init_irq(void) | |||
222 | static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs *regs) | 222 | static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs *regs) |
223 | { | 223 | { |
224 | u32 irqnr; | 224 | u32 irqnr; |
225 | int handled_irq = 0; | ||
225 | 226 | ||
226 | do { | 227 | do { |
227 | irqnr = readl_relaxed(base_addr + 0x98); | 228 | irqnr = readl_relaxed(base_addr + 0x98); |
@@ -249,8 +250,15 @@ out: | |||
249 | if (irqnr) { | 250 | if (irqnr) { |
250 | irqnr = irq_find_mapping(domain, irqnr); | 251 | irqnr = irq_find_mapping(domain, irqnr); |
251 | handle_IRQ(irqnr, regs); | 252 | handle_IRQ(irqnr, regs); |
253 | handled_irq = 1; | ||
252 | } | 254 | } |
253 | } while (irqnr); | 255 | } while (irqnr); |
256 | |||
257 | /* If an irq is masked or deasserted while active, we will | ||
258 | * keep ending up here with no irq handled. So remove it from | ||
259 | * the INTC with an ack.*/ | ||
260 | if (!handled_irq) | ||
261 | omap_ack_irq(NULL); | ||
254 | } | 262 | } |
255 | 263 | ||
256 | asmlinkage void __exception_irq_entry omap2_intc_handle_irq(struct pt_regs *regs) | 264 | asmlinkage void __exception_irq_entry omap2_intc_handle_irq(struct pt_regs *regs) |