diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/host/davinci_mmc.c | 33 |
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) { |