mmc: core: Re-work the code for eMMC sanitize
authorUlf Hansson <ulf.hansson@linaro.org>
Mon, 16 Mar 2020 15:21:52 +0000 (16:21 +0100)
committerUlf Hansson <ulf.hansson@linaro.org>
Thu, 26 Mar 2020 13:45:31 +0000 (14:45 +0100)
The error path for sanitize operations that completes with -ETIMEDOUT, is
tightly coupled with the internal request handling code of the core. More
precisely, mmc_wait_for_req_done() checks for specific sanitize errors.
This is not only inefficient as it affects all types of requests, but also
hackish.

Therefore, let's improve the behaviour by moving the error path out of the
mmc core. To do that, retuning needs to be held while running the sanitize
operation.

Moreover, to avoid exporting unnecessary symbols to the mmc block module,
let's move the code into the mmc_ops.c file. While updating the actual
code, let's also take the opportunity to clean up some of the mess around
it.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/r/20200316152152.15122-1-ulf.hansson@linaro.org
drivers/mmc/core/block.c
drivers/mmc/core/core.c
drivers/mmc/core/mmc_ops.c
drivers/mmc/core/mmc_ops.h
include/linux/mmc/core.h

index 7634894df853ced2026e442cc2235a28278b0a55..8499b56a15a8139211402d5b35048a411a3a391d 100644 (file)
@@ -70,7 +70,6 @@ MODULE_ALIAS("mmc:block");
  * ample.
  */
 #define MMC_BLK_TIMEOUT_MS  (10 * 1000)
-#define MMC_SANITIZE_REQ_TIMEOUT 240000
 #define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
 #define MMC_EXTRACT_VALUE_FROM_ARG(x) ((x & 0x0000FF00) >> 8)
 
@@ -413,34 +412,6 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
        return 0;
 }
 
-static int ioctl_do_sanitize(struct mmc_card *card)
-{
-       int err;
-
-       if (!mmc_can_sanitize(card)) {
-                       pr_warn("%s: %s - SANITIZE is not supported\n",
-                               mmc_hostname(card->host), __func__);
-                       err = -EOPNOTSUPP;
-                       goto out;
-       }
-
-       pr_debug("%s: %s - SANITIZE IN PROGRESS...\n",
-               mmc_hostname(card->host), __func__);
-
-       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                                       EXT_CSD_SANITIZE_START, 1,
-                                       MMC_SANITIZE_REQ_TIMEOUT);
-
-       if (err)
-               pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n",
-                      mmc_hostname(card->host), __func__, err);
-
-       pr_debug("%s: %s - SANITIZE COMPLETED\n", mmc_hostname(card->host),
-                                            __func__);
-out:
-       return err;
-}
-
 static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
                            u32 *resp_errs)
 {
@@ -569,15 +540,8 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
        }
 
        if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
-           (cmd.opcode == MMC_SWITCH)) {
-               err = ioctl_do_sanitize(card);
-
-               if (err)
-                       pr_err("%s: ioctl_do_sanitize() failed. err = %d",
-                              __func__, err);
-
-               return err;
-       }
+           (cmd.opcode == MMC_SWITCH))
+               return mmc_sanitize(card);
 
        mmc_wait_for_req(card->host, &mrq);
 
index 3f7a31456eb4fe4135688192fb28f7e5e4c868f7..4c5de6d37ac70e76ed2b329560ed667f7d4211eb 100644 (file)
@@ -403,23 +403,6 @@ void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq)
 
                cmd = mrq->cmd;
 
-               /*
-                * If host has timed out waiting for the sanitize
-                * to complete, card might be still in programming state
-                * so let's try to bring the card out of programming
-                * state.
-                */
-               if (cmd->sanitize_busy && cmd->error == -ETIMEDOUT) {
-                       if (!mmc_interrupt_hpi(host->card)) {
-                               pr_warn("%s: %s: Interrupted sanitize\n",
-                                       mmc_hostname(host), __func__);
-                               cmd->error = 0;
-                               break;
-                       } else {
-                               pr_err("%s: %s: Failed to interrupt sanitize\n",
-                                      mmc_hostname(host), __func__);
-                       }
-               }
                if (!cmd->error || !cmd->retries ||
                    mmc_card_removed(host->card))
                        break;
@@ -1925,7 +1908,6 @@ int mmc_can_sanitize(struct mmc_card *card)
                return 1;
        return 0;
 }
-EXPORT_SYMBOL(mmc_can_sanitize);
 
 int mmc_can_secure_erase_trim(struct mmc_card *card)
 {
index c75c00b5890d820957dd7f668136185068ee02ac..5bd0ab8b236a5707040b5c13bb5e204ff3a5938e 100644 (file)
@@ -21,6 +21,7 @@
 
 #define MMC_BKOPS_TIMEOUT_MS           (120 * 1000) /* 120s */
 #define MMC_CACHE_FLUSH_TIMEOUT_MS     (30 * 1000) /* 30s */
+#define MMC_SANITIZE_TIMEOUT_MS                (240 * 1000) /* 240s */
 
 static const u8 tuning_blk_pattern_4bit[] = {
        0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
@@ -597,9 +598,6 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
                cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
        }
 
-       if (index == EXT_CSD_SANITIZE_START)
-               cmd.sanitize_busy = true;
-
        err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
        if (err)
                goto out;
@@ -1032,3 +1030,37 @@ int mmc_cmdq_disable(struct mmc_card *card)
        return mmc_cmdq_switch(card, false);
 }
 EXPORT_SYMBOL_GPL(mmc_cmdq_disable);
+
+int mmc_sanitize(struct mmc_card *card)
+{
+       struct mmc_host *host = card->host;
+       int err;
+
+       if (!mmc_can_sanitize(card)) {
+               pr_warn("%s: Sanitize not supported\n", mmc_hostname(host));
+               return -EOPNOTSUPP;
+       }
+
+       pr_debug("%s: Sanitize in progress...\n", mmc_hostname(host));
+
+       mmc_retune_hold(host);
+
+       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_SANITIZE_START,
+                        1, MMC_SANITIZE_TIMEOUT_MS);
+       if (err)
+               pr_err("%s: Sanitize failed err=%d\n", mmc_hostname(host), err);
+
+       /*
+        * If the sanitize operation timed out, the card is probably still busy
+        * in the R1_STATE_PRG. Rather than continue to wait, let's try to abort
+        * it with a HPI command to get back into R1_STATE_TRAN.
+        */
+       if (err == -ETIMEDOUT && !mmc_interrupt_hpi(card))
+               pr_warn("%s: Sanitize aborted\n", mmc_hostname(host));
+
+       mmc_retune_release(host);
+
+       pr_debug("%s: Sanitize completed\n", mmc_hostname(host));
+       return err;
+}
+EXPORT_SYMBOL_GPL(mmc_sanitize);
index 38dcfeeaf6d58a1084074b3b0e8dcca97e45b2ba..632009260e51d2a34748658d82cf3791b4d0c3f7 100644 (file)
@@ -32,7 +32,6 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid);
 int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
 int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
 int mmc_bus_test(struct mmc_card *card, u8 bus_width);
-int mmc_interrupt_hpi(struct mmc_card *card);
 int mmc_can_ext_csd(struct mmc_card *card);
 int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);
 int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal);
@@ -47,6 +46,7 @@ void mmc_run_bkops(struct mmc_card *card);
 int mmc_flush_cache(struct mmc_card *card);
 int mmc_cmdq_enable(struct mmc_card *card);
 int mmc_cmdq_disable(struct mmc_card *card);
+int mmc_sanitize(struct mmc_card *card);
 
 #endif
 
index b7ba8810a3b533a6537312d837f4b2dc364748ed..29aa507116261f109bfbe36305d630bbbc622ef9 100644 (file)
@@ -107,9 +107,6 @@ struct mmc_command {
  */
 
        unsigned int            busy_timeout;   /* busy detect timeout in ms */
-       /* Set this flag only for blocking sanitize request */
-       bool                    sanitize_busy;
-
        struct mmc_data         *data;          /* data segment associated with cmd */
        struct mmc_request      *mrq;           /* associated request */
 };