Re: [PATCH] mmc: core: Modify the CMD1 transmission interval
From: Ulf Hansson
Date: Thu Sep 10 2026 - 09:22:37 EST
On Thu, Aug 27, 2026 at 11:15 AM Xiaojie Li <xiaojie.li2@xxxxxxxxxx> wrote:
>
> The current code's maximum udelay value is set to
> 64ms. Since it uses usleep_range(udelay, udelay*2),
> this results in a maximum wait time of 128ms between
> two consecutive CMD1 commands. For lower-performance eMMC chips,
> local testing shows that compared to the old code which used
> mmc_delay(10), the total time required to wait for the busy
> bit in the CMD1 response to change has increased by approximately
> 300ms, negatively impacting the overall eMMC initialization time.
Okay, that's not good.
>
> Although the current code sends the CMD1 command fewer times than
> the old version, the total waiting time is significantly longer.
> To address this, it's proposed to modify the CMD1 sending interval
> to follow a pattern like 4ms, 6ms, 8ms, 10ms, 10ms, etc., effectively
> capping the longest single wait at 10ms. Local testing confirms that
> this approach can bring the total time waiting for the busy state
> change very close to the performance level of the old code.
The code you refer to has been changed and fixed several times. We
need to be careful to not break support for some other cards. Please
have a look at the below commit for better understanding.
e949dee3625e ("mmc: core: Fix busy polling for MMC_SEND_OP_COND again")
1760fdb6fe9f ("mmc: core: Restore (almost) the busy polling for
MMC_SEND_OP_COND")
76bfc7ccc2fa ("mmc: core: adjust polling interval for CMD1")
That said, let's try to figure out how to improve this. See some more
comments below.
>
> The eMMC chip used for testing: manfid= 0x00009b, name= Y0S128, mdt= 2022-10
> The eMMC part number is: YMEC8B0TE2A2C3
>
> Signed-off-by: Xiaojie Li <xiaojie.li2@xxxxxxxxxx>
> ---
> drivers/mmc/core/mmc_ops.c | 85 ++++++++++++++++----------------------
> 1 file changed, 36 insertions(+), 49 deletions(-)
>
> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> index a952cc8265af..3076666cf2ca 100644
> --- a/drivers/mmc/core/mmc_ops.c
> +++ b/drivers/mmc/core/mmc_ops.c
> @@ -189,64 +189,51 @@ int mmc_go_idle(struct mmc_host *host)
> return err;
> }
>
> -static int __mmc_send_op_cond_cb(void *cb_data, bool *busy)
> -{
> - struct mmc_op_cond_busy_data *data = cb_data;
> - struct mmc_host *host = data->host;
> - struct mmc_command *cmd = data->cmd;
> - u32 ocr = data->ocr;
> - int err = 0;
> -
> - err = mmc_wait_for_cmd(host, cmd, 0);
> - if (err)
> - return err;
> -
> - if (mmc_host_is_spi(host)) {
> - if (!(cmd->resp[0] & R1_SPI_IDLE)) {
> - *busy = false;
> - return 0;
> - }
> - } else {
> - if (cmd->resp[0] & MMC_CARD_BUSY) {
> - *busy = false;
> - return 0;
> - }
> - }
> -
> - *busy = true;
> -
> - /*
> - * According to eMMC specification v5.1 section 6.4.3, we
> - * should issue CMD1 repeatedly in the idle state until
> - * the eMMC is ready. Otherwise some eMMC devices seem to enter
> - * the inactive mode after mmc_init_card() issued CMD0 when
> - * the eMMC device is busy.
> - */
> - if (!ocr && !mmc_host_is_spi(host))
> - cmd->arg = cmd->resp[0] | BIT(30);
> -
> - return 0;
> -}
> -
> int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
> {
> struct mmc_command cmd = {};
> + unsigned int udelay = MMC_OP_COND_PERIOD_US;
> + unsigned int udelay_max = 10000;
> + unsigned long timeout = jiffies + msecs_to_jiffies(MMC_OP_COND_TIMEOUT_MS) + 1;
> int err = 0;
> - struct mmc_op_cond_busy_data cb_data = {
> - .host = host,
> - .ocr = ocr,
> - .cmd = &cmd
> - };
>
> cmd.opcode = MMC_SEND_OP_COND;
> cmd.arg = mmc_host_is_spi(host) ? 0 : ocr;
> cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
>
> - err = __mmc_poll_for_busy(host, MMC_OP_COND_PERIOD_US,
> - MMC_OP_COND_TIMEOUT_MS,
> - &__mmc_send_op_cond_cb, &cb_data);
> - if (err)
> - return err;
> + while (!time_after(jiffies, timeout)) {
> + err = mmc_wait_for_cmd(host, &cmd, 0);
> + if (err)
> + break;
> +
> + if (mmc_host_is_spi(host)) {
> + if (!(cmd.resp[0] & R1_SPI_IDLE))
> + break;
> + } else {
> + if (cmd.resp[0] & MMC_CARD_BUSY)
> + break;
> + }
> +
> + /*
> + * According to eMMC specification v5.1 section 6.4.3, we
> + * should issue CMD1 repeatedly in the idle state until
> + * the eMMC is ready. Otherwise some eMMC devices seem to enter
> + * the inactive mode after mmc_init_card() issued CMD0 when
> + * the eMMC device is busy.
> + */
> + if (!ocr && !mmc_host_is_spi(host))
> + cmd.arg = cmd.resp[0] | BIT(30);
> +
> + usleep_range(udelay, udelay + 1000);
> +
> + if (udelay < udelay_max)
> + udelay += 2000;
> + else
> + udelay = udelay_max;
> + }
> +
> + if (time_after(jiffies, timeout))
> + err = -ETIMEDOUT;
We really need to avoid open coding of busy loops like this, as it
becomes a nightmare to maintain for us.
We have moved to use __mmc_poll_for_busy() for this reason, so let's
instead try to extend it to fit better for MMC_SEND_OP_COND.
I guess the most simple approach would be to add another parameter to
__mmc_poll_for_busy(), to allow us to specify a maximum polling
period. Can you please explore that approach instead?
>
> if (rocr && !mmc_host_is_spi(host))
> *rocr = cmd.resp[0];
> --
> 2.34.1
>
Kind regards
Uffe