All of lore.kernel.org
 help / color / mirror / Atom feed
* PATCH] mmc: block: ioctl: Poll for TRAN if possible
@ 2021-06-08  8:11 Christian Löhle
  2021-06-08  8:45 ` [PATCH] " Christian Löhle
  2021-06-08 11:22 ` PATCH] " Avri Altman
  0 siblings, 2 replies; 4+ messages in thread
From: Christian Löhle @ 2021-06-08  8:11 UTC (permalink / raw)
  To: linux-mmc, linux-kernel, ulf.hansson, Avri Altman, Adrian Hunter,
	shawn.lin

Poll for TRAN state if the ioctl command will eventually return to TRAN

The ioctl submitted command should not be considered completed until
the card has returned back to TRAN state. Waiting just for the card
to no longer signal busy is not enough as they might remain in a
non-busy PROG state for a while after the command.
Further commands requiring TRAN will fail then.
It should not be the responsibility of the user to check if their command
has completed until sending the next via ioctl,
instead the check should be made here.
So now, in doubt, wait for TRAN except for the few commands that will
never return to TRAN state.

Signed-off-by: Christian Loehle <cloehle@hyperstone.com>
---
 drivers/mmc/core/block.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 689eb9afeeed..a02187e4fad7 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -410,7 +410,23 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
 	return 0;
 }
 
-static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
+static int is_return_to_tran_cmd(struct mmc_command *cmd)
+{
+	/* Cards will never return to TRAN after completing
+	 * identification commands or MMC_SEND_STATUS if they are not selected.
+	 */
+	return !(cmd->opcode == MMC_SEND_CID
+			|| cmd->opcode == MMC_ALL_SEND_CID
+			|| cmd->opcode == MMC_SEND_CSD
+			|| cmd->opcode == MMC_SEND_STATUS
+			|| cmd->opcode == MMC_SELECT_CARD
+			|| cmd->opcode == MMC_APP_CMD
+			|| cmd->opcode == MMC_GO_INACTIVE_STATE
+			|| cmd->opcode == MMC_GO_IDLE_STATE);
+
+}
+
+static int card_poll_until_tran(struct mmc_card *card, unsigned int timeout_ms,
 			    u32 *resp_errs)
 {
 	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
@@ -593,12 +609,13 @@ 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 || (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
+	if (idata->rpmb || (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B
+			|| is_return_to_tran_cmd(&cmd)) {
 		/*
 		 * Ensure RPMB/R1B command has completed by polling CMD13
 		 * "Send Status".
 		 */
-		err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, NULL);
+		err = card_poll_until_tran(card, MMC_BLK_TIMEOUT_MS, NULL);
 	}
 
 	return err;
@@ -1621,7 +1638,7 @@ static int mmc_blk_fix_state(struct mmc_card *card, struct request *req)
 
 	mmc_blk_send_stop(card, timeout);
 
-	err = card_busy_detect(card, timeout, NULL);
+	err = card_poll_until_tran(card, timeout, NULL);
 
 	mmc_retune_release(card->host);
 
@@ -1845,7 +1862,7 @@ static int mmc_blk_card_busy(struct mmc_card *card, struct request *req)
 	if (mmc_host_is_spi(card->host) || rq_data_dir(req) == READ)
 		return 0;
 
-	err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, &status);
+	err = card_poll_until_tran(card, MMC_BLK_TIMEOUT_MS, &status);
 
 	/*
 	 * Do not assume data transferred correctly if there are any error bits
-- 
2.31.1
Hyperstone GmbH | Line-Eid-Strasse 3 | 78467 Konstanz
Managing Directors: Dr. Jan Peter Berns.
Commercial register of local courts: Freiburg HRB381782


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH] mmc: block: ioctl: Poll for TRAN if possible
  2021-06-08  8:11 PATCH] mmc: block: ioctl: Poll for TRAN if possible Christian Löhle
@ 2021-06-08  8:45 ` Christian Löhle
  2021-06-09 10:53   ` Avri Altman
  2021-06-08 11:22 ` PATCH] " Avri Altman
  1 sibling, 1 reply; 4+ messages in thread
From: Christian Löhle @ 2021-06-08  8:45 UTC (permalink / raw)
  To: linux-mmc, linux-kernel, ulf.hansson, Avri Altman, Adrian Hunter,
	shawn.lin

Poll for TRAN state if the ioctl command will eventually return to TRAN

The ioctl submitted command should not be considered completed until
the card has returned back to TRAN state. Waiting just for the card
to no longer signal busy is not enough as they might remain in a
non-busy PROG state for a while after the command.
Further commands requiring TRAN will fail then.
It should not be the responsibility of the user to check if their command
has completed until sending the next via ioctl,
instead the check should be made here.
So now, in doubt, wait for TRAN except for the few commands that will
never return to TRAN state.

Signed-off-by: Christian Loehle <cloehle@hyperstone.com>
---
 drivers/mmc/core/block.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 689eb9afeeed..a02187e4fad7 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -410,7 +410,23 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
         return 0;
 }
 
-static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
+static int is_return_to_tran_cmd(struct mmc_command *cmd)
+{
+       /* Cards will never return to TRAN after completing
+        * identification commands or MMC_SEND_STATUS if they are not selected.
+        */
+       return !(cmd->opcode == MMC_SEND_CID
+                       || cmd->opcode == MMC_ALL_SEND_CID
+                       || cmd->opcode == MMC_SEND_CSD
+                       || cmd->opcode == MMC_SEND_STATUS
+                       || cmd->opcode == MMC_SELECT_CARD
+                       || cmd->opcode == MMC_APP_CMD
+                       || cmd->opcode == MMC_GO_INACTIVE_STATE
+                       || cmd->opcode == MMC_GO_IDLE_STATE);
+
+}
+
+static int card_poll_until_tran(struct mmc_card *card, unsigned int timeout_ms,
                             u32 *resp_errs)
 {
         unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
@@ -593,12 +609,13 @@ 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 || (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
+       if (idata->rpmb || (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B
+                       || is_return_to_tran_cmd(&cmd)) {
                 /*
                  * Ensure RPMB/R1B command has completed by polling CMD13
                  * "Send Status".
                  */
-               err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, NULL);
+               err = card_poll_until_tran(card, MMC_BLK_TIMEOUT_MS, NULL);
         }
 
         return err;
@@ -1621,7 +1638,7 @@ static int mmc_blk_fix_state(struct mmc_card *card, struct request *req)
 
         mmc_blk_send_stop(card, timeout);
 
-       err = card_busy_detect(card, timeout, NULL);
+       err = card_poll_until_tran(card, timeout, NULL);
 
         mmc_retune_release(card->host);
 
@@ -1845,7 +1862,7 @@ static int mmc_blk_card_busy(struct mmc_card *card, struct request *req)
         if (mmc_host_is_spi(card->host) || rq_data_dir(req) == READ)
                 return 0;
 
-       err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, &status);
+       err = card_poll_until_tran(card, MMC_BLK_TIMEOUT_MS, &status);
 
         /*
          * Do not assume data transferred correctly if there are any error bits
-- 
2.31.1
Hyperstone GmbH | Line-Eid-Strasse 3 | 78467 Konstanz
Managing Directors: Dr. Jan Peter Berns.
Commercial register of local courts: Freiburg HRB381782


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* RE: PATCH] mmc: block: ioctl: Poll for TRAN if possible
  2021-06-08  8:11 PATCH] mmc: block: ioctl: Poll for TRAN if possible Christian Löhle
  2021-06-08  8:45 ` [PATCH] " Christian Löhle
@ 2021-06-08 11:22 ` Avri Altman
  1 sibling, 0 replies; 4+ messages in thread
From: Avri Altman @ 2021-06-08 11:22 UTC (permalink / raw)
  To: Christian Löhle, linux-mmc, linux-kernel, ulf.hansson,
	Adrian Hunter, shawn.lin

> Poll for TRAN state if the ioctl command will eventually return to TRAN
> 
> The ioctl submitted command should not be considered completed until
> the card has returned back to TRAN state. Waiting just for the card
> to no longer signal busy is not enough as they might remain in a
> non-busy PROG state for a while after the command.
> Further commands requiring TRAN will fail then.
> It should not be the responsibility of the user to check if their command
> has completed until sending the next via ioctl,
> instead the check should be made here.
> So now, in doubt, wait for TRAN except for the few commands that will
> never return to TRAN state.
Is this theoretical, or do you have an exact scenario in which the polling with cmd13 isn't enough?

Thanks,
Avri

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [PATCH] mmc: block: ioctl: Poll for TRAN if possible
  2021-06-08  8:45 ` [PATCH] " Christian Löhle
@ 2021-06-09 10:53   ` Avri Altman
  0 siblings, 0 replies; 4+ messages in thread
From: Avri Altman @ 2021-06-09 10:53 UTC (permalink / raw)
  To: Christian Löhle, linux-mmc, linux-kernel, ulf.hansson,
	Adrian Hunter, shawn.lin

> Poll for TRAN state if the ioctl command will eventually return to TRAN
> 
> The ioctl submitted command should not be considered completed until
> the card has returned back to TRAN state. Waiting just for the card
> to no longer signal busy is not enough as they might remain in a
> non-busy PROG state for a while after the command.
> Further commands requiring TRAN will fail then.
> It should not be the responsibility of the user to check if their command
> has completed until sending the next via ioctl,
> instead the check should be made here.
> So now, in doubt, wait for TRAN except for the few commands that will
> never return to TRAN state.
> 
> Signed-off-by: Christian Loehle <cloehle@hyperstone.com>
> ---
>  drivers/mmc/core/block.c | 27 ++++++++++++++++++++++-----
>  1 file changed, 22 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index 689eb9afeeed..a02187e4fad7 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -410,7 +410,23 @@ static int mmc_blk_ioctl_copy_to_user(struct
> mmc_ioc_cmd __user *ic_ptr,
>          return 0;
>  }
> 
> -static int card_busy_detect(struct mmc_card *card, unsigned int
> timeout_ms,
> +static int is_return_to_tran_cmd(struct mmc_command *cmd)
> +{
> +       /* Cards will never return to TRAN after completing
Multi-line comment style

> +        * identification commands or MMC_SEND_STATUS if they are not
> selected.
> +        */
> +       return !(cmd->opcode == MMC_SEND_CID
> +                       || cmd->opcode == MMC_ALL_SEND_CID
> +                       || cmd->opcode == MMC_SEND_CSD
> +                       || cmd->opcode == MMC_SEND_STATUS
> +                       || cmd->opcode == MMC_SELECT_CARD
> +                       || cmd->opcode == MMC_APP_CMD
> +                       || cmd->opcode == MMC_GO_INACTIVE_STATE
> +                       || cmd->opcode == MMC_GO_IDLE_STATE);
> +
Aren’t you only interested in cmds that move to tran state from other state?
According to the Device state transitions (table 61 in eMMC5.1) it only concern
cmd7 (stby->tran), cmd12 (data->tran), and cmd14 (btst->tran).

Thanks,
Avri
> +}
> +
> +static int card_poll_until_tran(struct mmc_card *card, unsigned int
> timeout_ms,
>                              u32 *resp_errs)
>  {
>          unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
> @@ -593,12 +609,13 @@ 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 || (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
> +       if (idata->rpmb || (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B
> +                       || is_return_to_tran_cmd(&cmd)) {
>                  /*
>                   * Ensure RPMB/R1B command has completed by polling CMD13
>                   * "Send Status".
>                   */
> -               err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, NULL);
> +               err = card_poll_until_tran(card, MMC_BLK_TIMEOUT_MS, NULL);
>          }
> 
>          return err;
> @@ -1621,7 +1638,7 @@ static int mmc_blk_fix_state(struct mmc_card
> *card, struct request *req)
> 
>          mmc_blk_send_stop(card, timeout);
> 
> -       err = card_busy_detect(card, timeout, NULL);
> +       err = card_poll_until_tran(card, timeout, NULL);
> 
>          mmc_retune_release(card->host);
> 
> @@ -1845,7 +1862,7 @@ static int mmc_blk_card_busy(struct mmc_card
> *card, struct request *req)
>          if (mmc_host_is_spi(card->host) || rq_data_dir(req) == READ)
>                  return 0;
> 
> -       err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, &status);
> +       err = card_poll_until_tran(card, MMC_BLK_TIMEOUT_MS, &status);
> 
>          /*
>           * Do not assume data transferred correctly if there are any error bits
> --
> 2.31.1
> Hyperstone GmbH | Line-Eid-Strasse 3 | 78467 Konstanz
> Managing Directors: Dr. Jan Peter Berns.
> Commercial register of local courts: Freiburg HRB381782


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-06-09 10:54 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-08  8:11 PATCH] mmc: block: ioctl: Poll for TRAN if possible Christian Löhle
2021-06-08  8:45 ` [PATCH] " Christian Löhle
2021-06-09 10:53   ` Avri Altman
2021-06-08 11:22 ` PATCH] " Avri Altman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.