Commit e2f04e18 authored by Matt Reimer's avatar Matt Reimer Committed by Russell King

[ARM] 3546/1: PATCH: subtle lost interrupts bug on i.MX

Patch from Matt Reimer

There is a subtle bug in the GPIO interrupt status register
handling in arch/arm/mach-imx/irq.c:imx_gpio_ack_irq(). The
documentation states that a 1 should be written to the relevant bit to
acknowledge a GPIO interrupt, but that is not what the code does.

The problem is that the |= writes back 1s for all the *other*
interrupts represented in the register, so interrupts could get lost.
For example, if interrupts are pending for GPIO B10 and B12, ISR_B
would have the value 0x00001400. Then when the interrupt code handles
GPIO B10, it eventually calls imx_gpio_ack_irq(IRQ_GPIOB(10)), which
effectively does this:

ISR_B |= 1 << 10;

with the result that (0x00001400 | 0x00000400) is written, clearing
the interrupt status bits for *both* GPIO B10 and B12.

The fix is to write 1s only for the interrupts we want to clear.

The same problem seems to be occurring in the DMA code; this patch
does not address those issues.
Acked-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: default avatarMatt Reimer <mreimer@vpop.net>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 0c27c5d5
...@@ -127,7 +127,7 @@ static void ...@@ -127,7 +127,7 @@ static void
imx_gpio_ack_irq(unsigned int irq) imx_gpio_ack_irq(unsigned int irq)
{ {
DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq); DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
ISR(IRQ_TO_REG(irq)) |= 1 << ((irq - IRQ_GPIOA(0)) % 32); ISR(IRQ_TO_REG(irq)) = 1 << ((irq - IRQ_GPIOA(0)) % 32);
} }
static void static void
......
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