diff options
author | Dong Aisheng <aisheng.dong@freescale.com> | 2015-07-06 16:39:11 +0800 |
---|---|---|
committer | Dong Aisheng <aisheng.dong@freescale.com> | 2015-07-10 16:56:28 +0800 |
commit | 7c339816043c2c9ab4ebfa094ceef9415bad8007 (patch) | |
tree | 60bfc0bfe965bec0962c7306e4bb78a14c566b94 | |
parent | fc590f7171a87660274147c5174d14b5750d7392 (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.c | 15 |
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; } |