diff options
author | Nicolas Serafini <nicolas.serafini@sensefly.com> | 2016-04-28 11:24:24 +0200 |
---|---|---|
committer | Dominik Sliwa <dominik.sliwa@toradex.com> | 2016-06-22 15:29:35 +0200 |
commit | 887872511354320f6e5000a390677c049033d764 (patch) | |
tree | 1a554908d7aed01db8caf3893f214d3236567b8b /drivers | |
parent | 0e6396ed35ce5ddf8825298f08faa4bb598d2750 (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.c | 13 |
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); |