mmc: core: Fix inconsistent sd3_bus_mode at UHS-I SD voltage switch failure
authorAdrian Hunter <adrian.hunter@intel.com>
Mon, 15 Aug 2022 07:33:21 +0000 (10:33 +0300)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 22 Aug 2022 10:58:28 +0000 (12:58 +0200)
If re-initialization results is a different signal voltage, because the
voltage switch failed previously, but not this time (or vice versa), then
sd3_bus_mode will be inconsistent with the card because the SD_SWITCH
command is done only upon first initialization.

Fix by always reading SD_SWITCH information during re-initialization, which
also means it does not need to be re-read later for the 1.8V fixup
workaround.

Note, brief testing showed SD_SWITCH took about 1.8ms to 2ms which added
about 1% to 1.5% to the re-initialization time, so it's not particularly
significant.

Reported-by: Seunghui Lee <sh043.lee@samsung.com>
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Seunghui Lee <sh043.lee@samsung.com>
Tested-by: Seunghui Lee <sh043.lee@samsung.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20220815073321.63382-3-adrian.hunter@intel.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/core/sd.c

index bc84d7d..06aa62c 100644 (file)
@@ -949,16 +949,17 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
 
                /* Erase init depends on CSD and SSR */
                mmc_init_erase(card);
-
-               /*
-                * Fetch switch information from card.
-                */
-               err = mmc_read_switch(card);
-               if (err)
-                       return err;
        }
 
        /*
+        * Fetch switch information from card. Note, sd3_bus_mode can change if
+        * voltage switch outcome changes, so do this always.
+        */
+       err = mmc_read_switch(card);
+       if (err)
+               return err;
+
+       /*
         * For SPI, enable CRC as appropriate.
         * This CRC enable is located AFTER the reading of the
         * card registers because some SDHC cards are not able
@@ -1480,26 +1481,15 @@ retry:
        if (!v18_fixup_failed && !mmc_host_is_spi(host) && mmc_host_uhs(host) &&
            mmc_sd_card_using_v18(card) &&
            host->ios.signal_voltage != MMC_SIGNAL_VOLTAGE_180) {
-               /*
-                * Re-read switch information in case it has changed since
-                * oldcard was initialized.
-                */
-               if (oldcard) {
-                       err = mmc_read_switch(card);
-                       if (err)
-                               goto free_card;
-               }
-               if (mmc_sd_card_using_v18(card)) {
-                       if (mmc_host_set_uhs_voltage(host) ||
-                           mmc_sd_init_uhs_card(card)) {
-                               v18_fixup_failed = true;
-                               mmc_power_cycle(host, ocr);
-                               if (!oldcard)
-                                       mmc_remove_card(card);
-                               goto retry;
-                       }
-                       goto cont;
+               if (mmc_host_set_uhs_voltage(host) ||
+                   mmc_sd_init_uhs_card(card)) {
+                       v18_fixup_failed = true;
+                       mmc_power_cycle(host, ocr);
+                       if (!oldcard)
+                               mmc_remove_card(card);
+                       goto retry;
                }
+               goto cont;
        }
 
        /* Initialization sequence for UHS-I cards */