Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: mmci: Handle CMD irq before DATA irq

In case of a read operation both MCI_CMDRESPEND and MCI_DATAEND can be
set in the status register when entering the interrupt handler. This is
due to that the card start sending data before the host has
acknowledged the command response.

To resolve the issue for this scenario, we must start by handling the
CMD irq instead of the DATA irq. The reason is beacuse the completion
of the DATA irq will not respect the current command and then causing
it to be garbled.

Cc: Russell King <linux@arm.linux.org.uk>
Cc: Johan Rudholm <jrudholm@gmail.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Chris Ball <chris@printf.net>

authored by

Ulf Hansson and committed by
Chris Ball
e7f3d222 bb5cba40

+5 -4
+5 -4
drivers/mmc/host/mmci.c
··· 1144 1144 1145 1145 dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status); 1146 1146 1147 + cmd = host->cmd; 1148 + if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT| 1149 + MCI_CMDRESPEND) && cmd) 1150 + mmci_cmd_irq(host, cmd, status); 1151 + 1147 1152 data = host->data; 1148 1153 if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR| 1149 1154 MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND| 1150 1155 MCI_DATABLOCKEND) && data) 1151 1156 mmci_data_irq(host, data, status); 1152 - 1153 - cmd = host->cmd; 1154 - if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd) 1155 - mmci_cmd_irq(host, cmd, status); 1156 1157 1157 1158 ret = 1; 1158 1159 } while (status);