summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorNicolas Serafini <nicolas.serafini@sensefly.com>2016-04-28 11:24:24 +0200
committerDominik Sliwa <dominik.sliwa@toradex.com>2016-06-22 15:29:35 +0200
commit887872511354320f6e5000a390677c049033d764 (patch)
tree1a554908d7aed01db8caf3893f214d3236567b8b /drivers
parent0e6396ed35ce5ddf8825298f08faa4bb598d2750 (diff)
mmc: sdhci: handle command timeout after transfer complete interrupt
On a tegra3 platform with Hynix eMMC we can observe that sometimes we receive a command timeout after a transfer complete interrupt on a multiple block read request. Here is the output using MMC_DEBUG and ftrace. When it works: tegra_sdhci_set_clock: tegra_sdhci_set_clock mmc0 0 enabled=1 tegra_sdhci_set_clock: tegra_sdhci_set_clock mmc0 52000000 enabled=0 __mmc_start_req: mmc0: starting CMD18 arg 00a73044 flags 000000b5 __mmc_start_req: mmc0: blksz 512 blocks 2 flags 00000200 tsac 150 ms nsac 1000 __mmc_start_req: mmc0: CMD12 arg 00000000 flags 0000049d sdhci_irq: sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000001 sdhci_finish_command: sdhci_finish_command:1075 sdhci_irq: sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002 sdhci_tasklet_finish: sdhci_tasklet_finish:2064 When we have the error: tegra_sdhci_set_clock: tegra_sdhci_set_clock mmc0 0 enabled=1 tegra_sdhci_set_clock: tegra_sdhci_set_clock mmc0 52000000 enabled=0 __mmc_start_req: mmc0: starting CMD18 arg 00a63d12 flags 000000b5 __mmc_start_req: mmc0: blksz 512 blocks 2 flags 00000200 tsac 150 ms nsac 1000 __mmc_start_req: mmc0: CMD12 arg 00000000 flags 0000049d sdhci_irq: sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000001 sdhci_finish_command: sdhci_finish_command:1075 sdhci_irq: sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00018000 ------NOW THE REQUEST BLOCK UNTIL TIMEOUT------ We can see that when it works the multiple read blocks command stopped by the CMD12 receive two interrupts. The first is the Transfer complete interrupt (SDHCI_INT_RESPONSE) and just after the Block Gap Event interrupt (SDHCI_INT_DATA_END). In this case the command is finished and the data is finished too. In the bad case instead of receiving SDHCI_INT_DATA_END we receive a command timeout error (SDHCI_INT_TIMEOUT) but command was already finished by the SDHCI_INT_RESPONSE so not more command is waiting and the driver wait until the timeout timer end because this case is not managed. Signed-off-by: Nicolas Serafini <nicolas.serafini@sensefly.com> Acked-by: Marcel Ziswiler <marcel.ziswiler@toradex.com> Acked-by: Dominik Sliwa <dominik.sliwa@toradex.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/sdhci.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 41b578299e66..292686676b51 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2118,6 +2118,19 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
BUG_ON(intmask == 0);
if (!host->cmd) {
+ if (host->mrq) {
+ if (intmask & SDHCI_INT_TIMEOUT) {
+ host->mrq->cmd->error = -ETIMEDOUT;
+ tasklet_schedule(&host->finish_tasklet);
+ return;
+ }
+ else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT |
+ SDHCI_INT_INDEX)) {
+ host->mrq->cmd->error = -EILSEQ;
+ tasklet_schedule(&host->finish_tasklet);
+ return;
+ }
+ }
printk(KERN_ERR "%s: Got command interrupt 0x%08x even "
"though no command operation was in progress.\n",
mmc_hostname(host->mmc), (unsigned)intmask);