From d916cbeabaaddea65be7e5fc86c0263eeb3a7455 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Sun, 11 Mar 2012 23:39:58 +0200 Subject: [PATCH] --- yaml --- r: 297352 b: refs/heads/master c: be7b5622e608189894c2c440c3fb0138f122071f h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/mmc/host/davinci_mmc.c | 33 +++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/[refs] b/[refs] index 7130b2eb522a..62834df3e36e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 1f84b71b3fa834faa87e14c8dc5d5a7c1fa084e8 +refs/heads/master: be7b5622e608189894c2c440c3fb0138f122071f diff --git a/trunk/drivers/mmc/host/davinci_mmc.c b/trunk/drivers/mmc/host/davinci_mmc.c index 8de9c9bdba0b..1e076fb06ac3 100644 --- a/trunk/drivers/mmc/host/davinci_mmc.c +++ b/trunk/drivers/mmc/host/davinci_mmc.c @@ -1009,12 +1009,33 @@ static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) * by read. So, it is not unbouned loop even in the case of * non-dma. */ - while (host->bytes_left && (status & (MMCST0_DXRDY | MMCST0_DRRDY))) { - davinci_fifo_data_trans(host, rw_threshold); - status = readl(host->base + DAVINCI_MMCST0); - if (!status) - break; - qstatus |= status; + if (host->bytes_left && (status & (MMCST0_DXRDY | MMCST0_DRRDY))) { + unsigned long im_val; + + /* + * If interrupts fire during the following loop, they will be + * handled by the handler, but the PIC will still buffer these. + * As a result, the handler will be called again to serve these + * needlessly. In order to avoid these spurious interrupts, + * keep interrupts masked during the loop. + */ + im_val = readl(host->base + DAVINCI_MMCIM); + writel(0, host->base + DAVINCI_MMCIM); + + do { + davinci_fifo_data_trans(host, rw_threshold); + status = readl(host->base + DAVINCI_MMCST0); + qstatus |= status; + } while (host->bytes_left && + (status & (MMCST0_DXRDY | MMCST0_DRRDY))); + + /* + * If an interrupt is pending, it is assumed it will fire when + * it is unmasked. This assumption is also taken when the MMCIM + * is first set. Otherwise, writing to MMCIM after reading the + * status is race-prone. + */ + writel(im_val, host->base + DAVINCI_MMCIM); } if (qstatus & MMCST0_DATDNE) {