mmc: block: Remove error check of hw_reset on reset
authorChristian Löhle <CLoehle@hyperstone.com>
Thu, 13 Oct 2022 11:16:37 +0000 (11:16 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Nov 2022 14:59:14 +0000 (23:59 +0900)
commit 406e14808ee695cbae1eafa5fd3ac563c29470ab upstream.

Before switching back to the right partition in mmc_blk_reset there used
to be a check if hw_reset was even supported. This return value
was removed, so there is no reason to check. Furthermore ensure
part_curr is not falsely set to a valid value on reset or
partition switch error.

As part of this change the code paths of mmc_blk_reset calls were checked
to ensure no commands are issued after a failed mmc_blk_reset directly
without going through the block layer.

Fixes: fefdd3c91e0a ("mmc: core: Drop superfluous validations in mmc_hw|sw_reset()")
Cc: stable@vger.kernel.org
Signed-off-by: Christian Loehle <cloehle@hyperstone.com>
Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
Link: https://lore.kernel.org/r/e91be6199d04414a91e20611c81bfe1d@hyperstone.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/mmc/core/block.c

index b2533be..ed034b9 100644 (file)
@@ -133,6 +133,7 @@ struct mmc_blk_data {
         * track of the current selected device partition.
         */
        unsigned int    part_curr;
+#define MMC_BLK_PART_INVALID   UINT_MAX        /* Unknown partition active */
        int     area_type;
 
        /* debugfs files (only in main mmc_blk_data) */
@@ -984,9 +985,16 @@ static unsigned int mmc_blk_data_timeout_ms(struct mmc_host *host,
        return ms;
 }
 
+/*
+ * Attempts to reset the card and get back to the requested partition.
+ * Therefore any error here must result in cancelling the block layer
+ * request, it must not be reattempted without going through the mmc_blk
+ * partition sanity checks.
+ */
 static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
                         int type)
 {
+       struct mmc_blk_data *main_md = dev_get_drvdata(&host->card->dev);
        int err;
 
        if (md->reset_done & type)
@@ -994,23 +1002,22 @@ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
 
        md->reset_done |= type;
        err = mmc_hw_reset(host);
+       /*
+        * A successful reset will leave the card in the main partition, but
+        * upon failure it might not be, so set it to MMC_BLK_PART_INVALID
+        * in that case.
+        */
+       main_md->part_curr = err ? MMC_BLK_PART_INVALID : main_md->part_type;
+       if (err)
+               return err;
        /* Ensure we switch back to the correct partition */
-       if (err) {
-               struct mmc_blk_data *main_md =
-                       dev_get_drvdata(&host->card->dev);
-               int part_err;
-
-               main_md->part_curr = main_md->part_type;
-               part_err = mmc_blk_part_switch(host->card, md->part_type);
-               if (part_err) {
-                       /*
-                        * We have failed to get back into the correct
-                        * partition, so we need to abort the whole request.
-                        */
-                       return -ENODEV;
-               }
-       }
-       return err;
+       if (mmc_blk_part_switch(host->card, md->part_type))
+               /*
+                * We have failed to get back into the correct
+                * partition, so we need to abort the whole request.
+                */
+               return -ENODEV;
+       return 0;
 }
 
 static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
@@ -1855,8 +1862,9 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req)
                return;
 
        /* Reset before last retry */
-       if (mqrq->retries + 1 == MMC_MAX_RETRIES)
-               mmc_blk_reset(md, card->host, type);
+       if (mqrq->retries + 1 == MMC_MAX_RETRIES &&
+           mmc_blk_reset(md, card->host, type))
+               return;
 
        /* Command errors fail fast, so use all MMC_MAX_RETRIES */
        if (brq->sbc.error || brq->cmd.error)