Skip to content

Commit decd4b2

Browse files
committed
Avoid retrying silent CMD8 probes on legacy SD cards
1 parent 58a0b88 commit decd4b2

2 files changed

Lines changed: 27 additions & 4 deletions

File tree

‎src/sdhci.c‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -914,14 +914,19 @@ static int sdcard_power_init_seq(uint32_t voltage)
914914
* SDHCI platforms deliberately: the delay is harmless settle
915915
* margin and the SD spec permits it. */
916916
udelay(200);
917-
/* Some hosts need more settling after CMD0. Retry a failed CMD8
918-
* before classifying a silent card as SD v1.x or a broken link. */
917+
/* A corrupted CMD8 response can be transient while the card settles
918+
* after CMD0. A timeout alone is how an SD v1.x card reports that it
919+
* does not implement CMD8, so do not repeat that silent probe. */
919920
for (retries = 0; retries < 10; retries++) {
920921
status = sdhci_cmd(SD_CMD8_SEND_IF_COND, SD_IF_COND_27V_33V,
921922
SDHCI_RESP_R7);
922923
cmd8_err = g_last_cmd_err;
923-
if (status == 0)
924+
if (status == 0 ||
925+
((cmd8_err & SDHCI_SRS12_ECT) != 0 &&
926+
(cmd8_err & (SDHCI_SRS12_ECCRC | SDHCI_SRS12_ECEB |
927+
SDHCI_SRS12_ECI)) == 0)) {
924928
break;
929+
}
925930
udelay(10000);
926931
}
927932
if (status == 0 && retries > 0) {

‎tools/unit-tests/unit-sdhci-cmd-inhibit.c‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ static int g_cmd8_never; /* v1.x: CMD8 is never answered */
6161
static int g_cmd8_needs_18v; /* left in UHS: answered only at 1.8V */
6262
static int g_cicmd_stuck; /* the command line never goes idle */
6363
static int g_cmd8_mangled; /* CMD8 IS answered, but the link corrupts it */
64+
static int g_cmd8_mangled_once; /* first CMD8 response is corrupted */
6465
static int g_reset_never; /* the reset bit itself never self-clears */
6566
static int g_inhibit_sticky; /* reset completes, but CICMD stays set */
6667
static unsigned int g_cmd8_attempts;
@@ -116,7 +117,8 @@ void sdhci_reg_write(uint32_t offset, uint32_t val)
116117
& SDHCI_SRS15_V18SE) != 0;
117118

118119
g_cmd8_attempts++;
119-
if (g_cmd8_mangled) {
120+
if (g_cmd8_mangled ||
121+
(g_cmd8_mangled_once && g_cmd8_attempts == 1)) {
120122
/* The card DID answer; the link mangled the response. Not a
121123
* timeout, so not a legacy card. */
122124
g_sdhci_regs[SDHCI_SRS12 / sizeof(uint32_t)] |=
@@ -184,6 +186,7 @@ static void setup(void)
184186
g_cmd8_never = 0;
185187
g_cmd8_needs_18v = 0;
186188
g_cmd8_mangled = 0;
189+
g_cmd8_mangled_once = 0;
187190
g_reset_never = 0;
188191
g_inhibit_sticky = 0;
189192
g_wdt_pets = 0;
@@ -275,6 +278,20 @@ START_TEST(test_uhs_recover_rolls_back)
275278
END_TEST
276279
#endif
277280

281+
/* A transient response error is retried; a working card still reaches
282+
* ACMD41 after its next CMD8 answer. */
283+
START_TEST(test_cmd8_transient_error_retries)
284+
{
285+
script_card_present();
286+
g_cmd8_mangled_once = 1;
287+
288+
(void)sdcard_card_full_init();
289+
290+
ck_assert_uint_eq(g_cmd8_attempts, 2);
291+
ck_assert_uint_gt(g_acmd41_polls, 0);
292+
}
293+
END_TEST
294+
278295
/* A mangled CMD8 response is NOT a legacy card.
279296
*
280297
* Silence means the card does not implement CMD8; a CRC or index error means
@@ -345,6 +362,7 @@ Suite *sdhci_cmd_inhibit_suite(void)
345362
tcase_add_test(tc, test_command_inhibit_does_not_hang);
346363
tcase_add_test(tc, test_cmd8_absent_is_not_fatal);
347364
tcase_add_test(tc, test_cmd8_answered_normally);
365+
tcase_add_test(tc, test_cmd8_transient_error_retries);
348366
tcase_add_test(tc, test_cmd8_bus_error_is_still_fatal);
349367
tcase_add_test(tc, test_inhibit_that_survives_reset_does_not_hang);
350368
tcase_add_test(tc, test_reset_that_never_clears_does_not_hang);

0 commit comments

Comments
 (0)