Title: [8979] trunk/drivers/mmc/host/mmc_spi.c: Fix bug[#5754]Recover from CRC error for SD read/write operation over SPI.
Revision
8979
Author
sonicz
Date
2010-07-09 04:04:21 -0400 (Fri, 09 Jul 2010)

Log Message

Fix bug[#5754]Recover from CRC error for SD read/write operation over SPI.

SPI bus is not reliable on all platforms when doing large dada transfer.
Current mmc spi driver fails SD read/write command immediately, if
occational CRC error is reported by SD device. This patch makes the
operation recover from the CRC error by doing last SD command again.
The retry count is set to 5 to ensure the driver pass any stress test.

Modified Paths

Diff

Modified: trunk/drivers/mmc/host/mmc_spi.c (8978 => 8979)


--- trunk/drivers/mmc/host/mmc_spi.c	2010-07-08 03:12:36 UTC (rev 8978)
+++ trunk/drivers/mmc/host/mmc_spi.c	2010-07-09 08:04:21 UTC (rev 8979)
@@ -1055,6 +1055,8 @@
 {
 	struct mmc_spi_host	*host = mmc_priv(mmc);
 	int			status = -EINVAL;
+	int			crc_retry = 5;
+	struct mmc_command	stop;
 
 #ifdef DEBUG
 	/* MMC core and layered drivers *MUST* issue SPI-aware commands */
@@ -1090,9 +1092,30 @@
 		dev_err(&host->spi->dev, "failed to lock spi bus\n");
 		return;
 	}
+
+crc_recover:
 	status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL);
 	if (status == 0 && mrq->data) {
 		mmc_spi_data_do(host, mrq->cmd, mrq->data, mrq->data->blksz);
+
+		/*
+		 * SPI bus is not reliable when doing large dada transfer.
+		 * If occational crc error is reported by SD device when do
+		 * data read/write over SPI, it can be recovered by doing
+		 * last SD command again. The retry count is set to 5 to
+		 * ensure the driver pass any stress test.
+		 */
+		if (mrq->data->error == -EILSEQ && crc_retry) {
+			stop.opcode = MMC_STOP_TRANSMISSION;
+			stop.arg = 0;
+			stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+
+			status = mmc_spi_command_send(host, mrq, &stop, 0);
+			crc_retry--;
+			mrq->data->error = 0;
+			goto crc_recover;
+		}
+
 		if (mrq->stop)
 			status = mmc_spi_command_send(host, mrq, mrq->stop, 0);
 		else
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to