aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/davinci_mmc.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 8de9c9bdba0b..1e076fb06ac3 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -1009,12 +1009,33 @@ static irqreturn_t mmc_davinci_irq(int irq, void *dev_id)
1009 * by read. So, it is not unbouned loop even in the case of 1009 * by read. So, it is not unbouned loop even in the case of
1010 * non-dma. 1010 * non-dma.
1011 */ 1011 */
1012 while (host->bytes_left && (status & (MMCST0_DXRDY | MMCST0_DRRDY))) { 1012 if (host->bytes_left && (status & (MMCST0_DXRDY | MMCST0_DRRDY))) {
1013 davinci_fifo_data_trans(host, rw_threshold); 1013 unsigned long im_val;
1014 status = readl(host->base + DAVINCI_MMCST0); 1014
1015 if (!status) 1015 /*
1016 break; 1016 * If interrupts fire during the following loop, they will be
1017 qstatus |= status; 1017 * handled by the handler, but the PIC will still buffer these.
1018 * As a result, the handler will be called again to serve these
1019 * needlessly. In order to avoid these spurious interrupts,
1020 * keep interrupts masked during the loop.
1021 */
1022 im_val = readl(host->base + DAVINCI_MMCIM);
1023 writel(0, host->base + DAVINCI_MMCIM);
1024
1025 do {
1026 davinci_fifo_data_trans(host, rw_threshold);
1027 status = readl(host->base + DAVINCI_MMCST0);
1028 qstatus |= status;
1029 } while (host->bytes_left &&
1030 (status & (MMCST0_DXRDY | MMCST0_DRRDY)));
1031
1032 /*
1033 * If an interrupt is pending, it is assumed it will fire when
1034 * it is unmasked. This assumption is also taken when the MMCIM
1035 * is first set. Otherwise, writing to MMCIM after reading the
1036 * status is race-prone.
1037 */
1038 writel(im_val, host->base + DAVINCI_MMCIM);
1018 } 1039 }
1019 1040
1020 if (qstatus & MMCST0_DATDNE) { 1041 if (qstatus & MMCST0_DATDNE) {