mmc: sh_mmcif: process error interrupts first
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Wed, 14 Dec 2011 18:31:51 +0000 (19:31 +0100)
committerChris Ball <cjb@laptop.org>
Thu, 12 Jan 2012 04:58:45 +0000 (23:58 -0500)
If an interrupt is coming with both error and data completion status bits
set, it has to be handled as an error interrupt, for which error interrupts
have to be processed first. The current version of the driver on the
contrary doesn't recognise such interrupts as an error event, which leads
to data corruption and breaks the error recovery.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Chris Ball <cjb@laptop.org>
drivers/mmc/host/sh_mmcif.c

index 7bec007bcefafcddb5e691df07aeccc5a910b54a..0cba85a7f561944243b58e5b5d22ac24f48a74c8 100644 (file)
@@ -961,7 +961,12 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
 
        state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
 
-       if (state & INT_RBSYE) {
+       if (state & INT_ERR_STS) {
+               /* error interrupts - process first */
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
+               sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
+               err = 1;
+       } else if (state & INT_RBSYE) {
                sh_mmcif_writel(host->addr, MMCIF_CE_INT,
                                ~(INT_RBSYE | INT_CRSPE));
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MRBSYE);
@@ -989,11 +994,6 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
                sh_mmcif_writel(host->addr, MMCIF_CE_INT,
                                ~(INT_CMD12RBE | INT_CMD12CRE));
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE);
-       } else if (state & INT_ERR_STS) {
-               /* err interrupts */
-               sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
-               sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
-               err = 1;
        } else {
                dev_dbg(&host->pd->dev, "Unsupported interrupt: 0x%x\n", state);
                sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);