summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDong Aisheng <aisheng.dong@freescale.com>2015-07-06 16:39:11 +0800
committerDong Aisheng <aisheng.dong@freescale.com>2015-07-10 16:56:28 +0800
commit7c339816043c2c9ab4ebfa094ceef9415bad8007 (patch)
tree60bfc0bfe965bec0962c7306e4bb78a14c566b94
parentfc590f7171a87660274147c5174d14b5750d7392 (diff)
MLK-11184 mmc: sdhci: wait data error interrupts to handle transfer error for data commands
Due to the data may be still in transferring if a cmd error of data command happens, the next quick reset during data transfer may cause host controller unpridicable issues. e.g. On MX6Q/MX6QP, if reset during ADMA is busy moving data from FIFO to memory, we can observe 32 bytes lost issue sometimes in a very lower possibility especially for SD3.0 cards because the tuning command can easily fail on cmd error before data transfer complete. Let's using data error interrupts to handle transfer error of a data command instead of only checking cmd error, then can make sure the next safe reset only happens when data transfer is done. After fixing, the SD3.0 can pass 3 days reboot stress test while it could easily fail on only one night stress test before. Signed-off-by: Dong Aisheng <aisheng.dong@freescale.com>
-rw-r--r--drivers/mmc/host/sdhci.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index b513fa1ef13b..6775ac6894fb 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2353,7 +2353,20 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
host->cmd->error = -EILSEQ;
if (host->cmd->error) {
- tasklet_schedule(&host->finish_tasklet);
+ if (!host->cmd->data || host->data_early) {
+ tasklet_schedule(&host->finish_tasklet);
+ } else {
+ /*
+ * data may be still in transferring, wait for data
+ * interrupts to handle errors to avoid reset
+ * during data transfer which may cause unpridicable
+ * issues due to controller internal state wrong.
+ *
+ * Need clear host->cmd to avoid wrongly set data_early
+ * in the later sdhci_data_irq.
+ */
+ host->cmd = NULL;
+ }
return;
}