summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMatt Reimer <mreimer@vpop.net>2006-06-08 22:46:48 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-06-08 22:46:48 +0100
commite2f04e18941dbd3826901540a0be03f1728f8822 (patch)
tree1a52bcac2d2f165089d7784025659f21e6db57b0 /arch
parent0c27c5d5b93339df4def7ced77ea5be26df4d84b (diff)
downloadlinux-e2f04e18941dbd3826901540a0be03f1728f8822.tar.gz
linux-e2f04e18941dbd3826901540a0be03f1728f8822.tar.bz2
linux-e2f04e18941dbd3826901540a0be03f1728f8822.zip
[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: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Matt Reimer <mreimer@vpop.net> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/irq.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/arch/arm/mach-imx/irq.c b/arch/arm/mach-imx/irq.c
index eeb8a6d4a399..a5de5f1da9f2 100644
--- a/arch/arm/mach-imx/irq.c
+++ b/arch/arm/mach-imx/irq.c
@@ -127,7 +127,7 @@ static void
imx_gpio_ack_irq(unsigned int 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