Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 3 Jun 2021 01:49:03 GMT
From:      Warner Losh <imp@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: e7dc08415a32 - main - mmc: ignore CRC errors from CMD13 (status) when changing rates
Message-ID:  <202106030149.1531n3xr086674@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=e7dc08415a324d1000cd067fbc12b1ec79e0b2ac

commit e7dc08415a324d1000cd067fbc12b1ec79e0b2ac
Author:     Austin Shafer <ashafer@badland.io>
AuthorDate: 2021-06-03 01:46:23 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2021-06-03 01:46:23 +0000

    mmc: ignore CRC errors from CMD13 (status) when changing rates
    
    Update mmc_switch_status to ignore a few CRC errrors when asking for the
    card status after setting the new rate with CMD6. Since the card may
    take a little while to make the switch, it's possible we'll get a
    communications error if we sent the command at the wrong time. Several
    low end laptops needs this workaround as they have a window that seems
    longer than other systems. This is known to fix at least the Acer Aspire
    A114-32-P7E5.
    
    Reviewed by:            imp@, manu@
    Differential Revision:  https://reviews.freebsd.org/D24740
---
 sys/dev/mmc/mmc_subr.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/sys/dev/mmc/mmc_subr.c b/sys/dev/mmc/mmc_subr.c
index 53c9009c6e64..b43a233820bb 100644
--- a/sys/dev/mmc/mmc_subr.c
+++ b/sys/dev/mmc/mmc_subr.c
@@ -193,7 +193,7 @@ int
 mmc_switch_status(device_t busdev, device_t dev, uint16_t rca, u_int timeout)
 {
 	struct timeval cur, end;
-	int err;
+	int err, crc_timeout;
 	uint32_t status;
 
 	KASSERT(timeout != 0, ("%s: no timeout", __func__));
@@ -205,7 +205,19 @@ mmc_switch_status(device_t busdev, device_t dev, uint16_t rca, u_int timeout)
 	 */
 	end.tv_sec = end.tv_usec = 0;
 	for (;;) {
-		err = mmc_send_status(busdev, dev, rca, &status);
+		crc_timeout=0;
+		do {
+			/*
+			 * CRC errors indicate that the command wasn't accepted
+			 * and executed due to a communications error. Retry
+			 * CRC errors a couple of times to cope with transient
+			 * failures.
+			 *
+			 * This is required for some cheap laptops to boot.
+			 */
+			err = mmc_send_status(busdev, dev, rca, &status);
+			crc_timeout++;
+		} while (err == MMC_ERR_BADCRC && crc_timeout < 10);
 		if (err != MMC_ERR_NONE)
 			break;
 		if (R1_CURRENT_STATE(status) == R1_STATE_TRAN)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202106030149.1531n3xr086674>