aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorSonic Zhang <sonic.zhang@analog.com>2010-07-12 03:50:56 -0400
committerChris Ball <cjb@laptop.org>2010-10-23 09:11:22 -0400
commit061c6c847eeb11743e489a16e907b41c6f9042b6 (patch)
tree37bb835b50342cc459366e36da1117b137760f6d /drivers/mmc
parent95f25efe0ce22e28d61722d655d2ef582f5f7520 (diff)
mmc_spi: Recover from CRC errors for r/w operation over SPI.
The SPI bus is not reliable for large data transfers on all platforms. The current mmc_spi driver fails SD read/write commands immediately if occasional CRC errors are reported by the SD device. This patch makes the operation recover from CRC errors by repeating the last SD command. The retry count is set to 5 to ensure the driver passes stress tests. Signed-off-by: Sonic Zhang <sonic.zhang@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/mmc_spi.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 5b0b50636ec4..fd877f633dd2 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1055,6 +1055,8 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq)
1055{ 1055{
1056 struct mmc_spi_host *host = mmc_priv(mmc); 1056 struct mmc_spi_host *host = mmc_priv(mmc);
1057 int status = -EINVAL; 1057 int status = -EINVAL;
1058 int crc_retry = 5;
1059 struct mmc_command stop;
1058 1060
1059#ifdef DEBUG 1061#ifdef DEBUG
1060 /* MMC core and layered drivers *MUST* issue SPI-aware commands */ 1062 /* MMC core and layered drivers *MUST* issue SPI-aware commands */
@@ -1087,10 +1089,29 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq)
1087 /* request exclusive bus access */ 1089 /* request exclusive bus access */
1088 spi_bus_lock(host->spi->master); 1090 spi_bus_lock(host->spi->master);
1089 1091
1092crc_recover:
1090 /* issue command; then optionally data and stop */ 1093 /* issue command; then optionally data and stop */
1091 status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL); 1094 status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL);
1092 if (status == 0 && mrq->data) { 1095 if (status == 0 && mrq->data) {
1093 mmc_spi_data_do(host, mrq->cmd, mrq->data, mrq->data->blksz); 1096 mmc_spi_data_do(host, mrq->cmd, mrq->data, mrq->data->blksz);
1097
1098 /*
1099 * The SPI bus is not always reliable for large data transfers.
1100 * If an occasional crc error is reported by the SD device with
1101 * data read/write over SPI, it may be recovered by repeating
1102 * the last SD command again. The retry count is set to 5 to
1103 * ensure the driver passes stress tests.
1104 */
1105 if (mrq->data->error == -EILSEQ && crc_retry) {
1106 stop.opcode = MMC_STOP_TRANSMISSION;
1107 stop.arg = 0;
1108 stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
1109 status = mmc_spi_command_send(host, mrq, &stop, 0);
1110 crc_retry--;
1111 mrq->data->error = 0;
1112 goto crc_recover;
1113 }
1114
1094 if (mrq->stop) 1115 if (mrq->stop)
1095 status = mmc_spi_command_send(host, mrq, mrq->stop, 0); 1116 status = mmc_spi_command_send(host, mrq, mrq->stop, 0);
1096 else 1117 else