mmc: block: Add CMD13 polling for MMC IOCTLS with R1B response
authorChaotian Jing <chaotian.jing@mediatek.com>
Thu, 5 Sep 2019 07:53:18 +0000 (15:53 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 21 Dec 2019 10:04:23 +0000 (11:04 +0100)
commit a0d4c7eb71dd08a89ad631177bb0cbbabd598f84 upstream.

MMC IOCTLS with R1B responses may cause the card to enter the busy state,
which means it's not ready to receive a new request. To prevent new
requests from being sent to the card, use a CMD13 polling loop to verify
that the card returns to the transfer state, before completing the request.

Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
Reviewed-by: Avri Altman <avri.altman@wdc.com>
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/mmc/core/block.c

index aa7c19f..95b41c0 100644 (file)
@@ -408,38 +408,6 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
        return 0;
 }
 
-static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
-                                      u32 retries_max)
-{
-       int err;
-       u32 retry_count = 0;
-
-       if (!status || !retries_max)
-               return -EINVAL;
-
-       do {
-               err = __mmc_send_status(card, status, 5);
-               if (err)
-                       break;
-
-               if (!R1_STATUS(*status) &&
-                               (R1_CURRENT_STATE(*status) != R1_STATE_PRG))
-                       break; /* RPMB programming operation complete */
-
-               /*
-                * Rechedule to give the MMC device a chance to continue
-                * processing the previous command without being polled too
-                * frequently.
-                */
-               usleep_range(1000, 5000);
-       } while (++retry_count < retries_max);
-
-       if (retry_count == retries_max)
-               err = -EPERM;
-
-       return err;
-}
-
 static int ioctl_do_sanitize(struct mmc_card *card)
 {
        int err;
@@ -468,6 +436,58 @@ out:
        return err;
 }
 
+static inline bool mmc_blk_in_tran_state(u32 status)
+{
+       /*
+        * Some cards mishandle the status bits, so make sure to check both the
+        * busy indication and the card state.
+        */
+       return status & R1_READY_FOR_DATA &&
+              (R1_CURRENT_STATE(status) == R1_STATE_TRAN);
+}
+
+static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
+                           u32 *resp_errs)
+{
+       unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
+       int err = 0;
+       u32 status;
+
+       do {
+               bool done = time_after(jiffies, timeout);
+
+               err = __mmc_send_status(card, &status, 5);
+               if (err) {
+                       dev_err(mmc_dev(card->host),
+                               "error %d requesting status\n", err);
+                       return err;
+               }
+
+               /* Accumulate any response error bits seen */
+               if (resp_errs)
+                       *resp_errs |= status;
+
+               /*
+                * Timeout if the device never becomes ready for data and never
+                * leaves the program state.
+                */
+               if (done) {
+                       dev_err(mmc_dev(card->host),
+                               "Card stuck in wrong state! %s status: %#x\n",
+                                __func__, status);
+                       return -ETIMEDOUT;
+               }
+
+               /*
+                * Some cards mishandle the status bits,
+                * so make sure to check both the busy
+                * indication and the card state.
+                */
+       } while (!mmc_blk_in_tran_state(status));
+
+       return err;
+}
+
 static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
                               struct mmc_blk_ioc_data *idata)
 {
@@ -477,7 +497,6 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
        struct scatterlist sg;
        int err;
        unsigned int target_part;
-       u32 status = 0;
 
        if (!card || !md || !idata)
                return -EINVAL;
@@ -611,16 +630,12 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
 
        memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp));
 
-       if (idata->rpmb) {
+       if (idata->rpmb || (cmd.flags & MMC_RSP_R1B)) {
                /*
-                * Ensure RPMB command has completed by polling CMD13
+                * Ensure RPMB/R1B command has completed by polling CMD13
                 * "Send Status".
                 */
-               err = ioctl_rpmb_card_status_poll(card, &status, 5);
-               if (err)
-                       dev_err(mmc_dev(card->host),
-                                       "%s: Card Status=0x%08X, error %d\n",
-                                       __func__, status, err);
+               err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, NULL);
        }
 
        return err;
@@ -970,58 +985,6 @@ static unsigned int mmc_blk_data_timeout_ms(struct mmc_host *host,
        return ms;
 }
 
-static inline bool mmc_blk_in_tran_state(u32 status)
-{
-       /*
-        * Some cards mishandle the status bits, so make sure to check both the
-        * busy indication and the card state.
-        */
-       return status & R1_READY_FOR_DATA &&
-              (R1_CURRENT_STATE(status) == R1_STATE_TRAN);
-}
-
-static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
-                           u32 *resp_errs)
-{
-       unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
-       int err = 0;
-       u32 status;
-
-       do {
-               bool done = time_after(jiffies, timeout);
-
-               err = __mmc_send_status(card, &status, 5);
-               if (err) {
-                       dev_err(mmc_dev(card->host),
-                               "error %d requesting status\n", err);
-                       return err;
-               }
-
-               /* Accumulate any response error bits seen */
-               if (resp_errs)
-                       *resp_errs |= status;
-
-               /*
-                * Timeout if the device never becomes ready for data and never
-                * leaves the program state.
-                */
-               if (done) {
-                       dev_err(mmc_dev(card->host),
-                               "Card stuck in wrong state! %s status: %#x\n",
-                                __func__, status);
-                       return -ETIMEDOUT;
-               }
-
-               /*
-                * Some cards mishandle the status bits,
-                * so make sure to check both the busy
-                * indication and the card state.
-                */
-       } while (!mmc_blk_in_tran_state(status));
-
-       return err;
-}
-
 static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
                         int type)
 {