summaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2016-11-21 15:49:48 +0100
committerUlf Hansson <ulf.hansson@linaro.org>2016-11-29 09:05:24 +0100
commit5ec32f84111a500c142961c82dd415c22e64e2be (patch)
tree31c5194aa219d6ae645275bf8bdffd6ed6ba5ac1 /drivers/mmc
parent625228fa3e017d80f547b35214c60b4081b5c07d (diff)
downloadlinux-5ec32f84111a500c142961c82dd415c22e64e2be.tar.bz2
mmc: core: Check SWITCH_ERROR bit from each CMD13 response when polling
According to the JEDEC specification, the SWITCH_ERROR bit in the device status from a R1 response, is an error bit which may be cleared as soon as the response that reports the error is sent. When polling with CMD13 to find out when the card stops signaling busy after a CMD6 has been sent, we currently parse only the last CMD13 response for the SWITCH_ERROR bit. Consequentially we could loose important information about the card. In worst case if the card stops signaling busy within the allowed timeout, we could end up believing that the CMD6 command completed successfully, when in fact it didn't. To improve the behaviour, let's parse each CMD13 response to see if the SWITCH_ERROR bit is set in the device status. In such case, we abort the polling loop and report the error. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Tested-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/mmc_ops.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 214e7342e946..fba5d2954165 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -496,12 +496,16 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
busy = host->ops->card_busy(host);
} else {
err = mmc_send_status(card, &status);
- if (retry_crc_err && err == -EILSEQ)
+ if (retry_crc_err && err == -EILSEQ) {
busy = true;
- else if (err)
+ } else if (err) {
return err;
- else
+ } else {
+ err = mmc_switch_status_error(host, status);
+ if (err)
+ return err;
busy = R1_CURRENT_STATE(status) == R1_STATE_PRG;
+ }
}
/* Timeout if the device still remains busy. */
@@ -515,7 +519,7 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
if (host->ops->card_busy && send_status)
return mmc_switch_status(card);
- return mmc_switch_status_error(host, status);
+ return 0;
}
/**