summaryrefslogtreecommitdiff
path: root/drivers/mmc/host/dw_mmc.c
diff options
context:
space:
mode:
authorMårten Lindahl <marten.lindahl@axis.com>2021-12-20 14:30:26 +0300
committerUlf Hansson <ulf.hansson@linaro.org>2021-12-21 15:28:41 +0300
commit1a6fe7bbc7d28e619377232a9810c822299112aa (patch)
tree65834de6035e62b2de839ef40c1ee214beafe46b /drivers/mmc/host/dw_mmc.c
parent25d5417a90fd44cefa9af670ca358cae2f184f8b (diff)
downloadlinux-1a6fe7bbc7d28e619377232a9810c822299112aa.tar.xz
mmc: dw_mmc: Do not wait for DTO in case of error
When running the ARTPEC-8 DWMMC IP version, and a data error interrupt comes during a data read transfer, there is no guarantee for the data transfer over interrupt (DTO) to come within the specified data timeout. This case is handled by the dto_timer handler which will complete the request with the comment: /* * If DTO interrupt does NOT come in sending data state, * we should notify the driver to terminate current transfer * and report a data timeout to the core. */ But since the ARTPEC-8 DWMMC IP version, supports an extended TMOUT register which allows longer timeouts than the non ARTPEC-8 version does, waiting for the dto_timer to complete the request in error cases may cause the request to take significantly longer time than necessary. This is specifically true for the failing steps during tuning of a device. Fix this by completing the request when the error interrupt comes. Since this fix is specific for the ARTPEC-8, a quirk is added. Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com> Link: https://lore.kernel.org/r/20211220113026.21129-5-marten.lindahl@axis.com Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc/host/dw_mmc.c')
-rw-r--r--drivers/mmc/host/dw_mmc.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 05b72b3c5dc0..42bf8a2287ba 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -2762,11 +2762,20 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
if (pending & DW_MCI_DATA_ERROR_FLAGS) {
spin_lock(&host->irq_lock);
+ if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT)
+ del_timer(&host->dto_timer);
+
/* if there is an error report DATA_ERROR */
mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS);
host->data_status = pending;
smp_wmb(); /* drain writebuffer */
set_bit(EVENT_DATA_ERROR, &host->pending_events);
+
+ if (host->quirks & DW_MMC_QUIRK_EXTENDED_TMOUT)
+ /* In case of error, we cannot expect a DTO */
+ set_bit(EVENT_DATA_COMPLETE,
+ &host->pending_events);
+
tasklet_schedule(&host->tasklet);
spin_unlock(&host->irq_lock);