mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v3 0/4] mmc: meson-gx: honour the busy timeout for R1b commands
@ 2026-10-09 17:02 Igor Velkov via B4 Relay
  2026-10-09 17:02 ` [PATCH v3 1/4] mmc: meson-gx: name the limit of the CMD_CFG timeout field Igor Velkov via B4 Relay
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Igor Velkov via B4 Relay @ 2026-10-09 17:02 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
	linux-mmc, linux-amlogic, linux-arm-kernel, linux-kernel,
	Igor Velkov

For a command without data the driver programs a fixed 1024 ms into the
CMD_CFG timeout field and does not tell the core how long the controller
can wait for busy. Erase and cache flush then fail with -110 on eMMC.
Patch 3 fixes card_busy, which reported a busy card free; patch 4 makes
the core rely on it.

Tested on ODROID-N2+ (S922X), 256 GB eMMC, btrfs root with discard=async,
Armbian builds in docker as load. Without the series (7.3-rc6): 262
errors in 3 h and 68 in 2.5 h in two runs; the first came 4 and 43 min
into the build. With v1 (7.3-rc6): 0 in 16 h, 2.4 h of it under the
build. With v3: 0 in a 37 min kernel build and in a 20 GiB write +
fstrim; a sanitize went out as R1 and the core polled DAT0 for 523 ms
until the card was back in TRAN. On 7.1 with the previous eMMC module
a synthetic test (20 GiB write + fstrim) gave 48 errors without the
patches, 0 and 0 with them.

ODROID-N2 (S922X), 128 GB Kingston eMMC, 20 GiB write + fstrim:
without the series an erase hit the 1024 ms limit and failed with -110
in 3 of 3 runs. With v3, in 3 such runs and a fill of the card to 85 %
with rm + fstrim, 5 erases took over 1024 ms, up to 1219 ms, and
completed; 0 errors.

ODROID-HC4, SD card in SDR104 at 1.8 V: 0 errors in 5 boots.

The timeout is rounded up to a power of two: the field holds powers of
two only, and the timeout is a lower bound. MMC_CAP_WAIT_WHILE_BUSY is
not set: I have not checked that the controller waits for busy on every
R1b command, HS400 switches included.

---
Changes in v3:
- Clamp cmd->busy_timeout to the range of the field before rounding it
  up to a power of two: the rounding of a value above 2^31 overflowed
  unsigned int (Sashiko).
- New patch 3: card_busy reports busy from DAT0 alone. It required
  DAT0..3 all low and reported a busy card free (Sashiko).
- Link to v2: https://lore.kernel.org/r/20261008-meson-gx-busy-timeout-v2-0-8bde1adfb5b4@iav.lv

Changes in v2:
- Split into three patches, as Neil asked: name the limit of the
  timeout field, program the R1b timeout from cmd->busy_timeout, report
  max_busy_timeout.
- Link to v1: https://lore.kernel.org/r/20261008-meson-gx-busy-timeout-v1-1-d92f3c68c409@iav.lv

---
Igor Velkov (4):
      mmc: meson-gx: name the limit of the CMD_CFG timeout field
      mmc: meson-gx: honour the busy timeout for R1b commands
      mmc: meson-gx: report busy from DAT0 alone
      mmc: meson-gx: report the longest busy wait the controller can do

 drivers/mmc/host/meson-gx-mmc.c | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)
---
base-commit: fd9af27f6c2319713bb23832066585f8a59a1771
change-id: 20261005-meson-gx-busy-timeout-7e8e3fdcb3e3

Best regards,
-- 
Igor Velkov <iav@iav.lv>



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

* [PATCH v3 1/4] mmc: meson-gx: name the limit of the CMD_CFG timeout field
  2026-10-09 17:02 [PATCH v3 0/4] mmc: meson-gx: honour the busy timeout for R1b commands Igor Velkov via B4 Relay
@ 2026-10-09 17:02 ` Igor Velkov via B4 Relay
  2026-10-09 17:02 ` [PATCH v3 2/4] mmc: meson-gx: honour the busy timeout for R1b commands Igor Velkov via B4 Relay
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Igor Velkov via B4 Relay @ 2026-10-09 17:02 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
	linux-mmc, linux-amlogic, linux-arm-kernel, linux-kernel,
	Igor Velkov

From: Igor Velkov <iav@iav.lv>

The data timeout is capped at a literal 32768 ms with a comment next to
it. Give the limit a name beside the other timeout constants.

Assisted-by: LLM
Signed-off-by: Igor Velkov <iav@iav.lv>
---
 drivers/mmc/host/meson-gx-mmc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index 7ef16d7c03cb..06479ba38525 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -125,6 +125,7 @@
 #define SD_EMMC_CFG_RESP_TIMEOUT 256 /* in clock cycles */
 #define SD_EMMC_CMD_TIMEOUT 1024 /* in ms */
 #define SD_EMMC_CMD_TIMEOUT_DATA 4096 /* in ms */
+#define SD_EMMC_CMD_TIMEOUT_MAX 32768 /* in ms, 2^15: limit of CMD_CFG_TIMEOUT_MASK */
 #define SD_EMMC_CFG_CMD_GAP 16 /* in clock cycles */
 #define SD_EMMC_DESC_BUF_LEN PAGE_SIZE
 
@@ -212,7 +213,7 @@ static unsigned int meson_mmc_get_timeout_msecs(struct mmc_data *data)
 
 	timeout = roundup_pow_of_two(timeout);
 
-	return min(timeout, 32768U); /* max. 2^15 ms */
+	return min_t(unsigned int, timeout, SD_EMMC_CMD_TIMEOUT_MAX);
 }
 
 static struct mmc_command *meson_mmc_get_next_command(struct mmc_command *cmd)

-- 
2.43.0



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

* [PATCH v3 2/4] mmc: meson-gx: honour the busy timeout for R1b commands
  2026-10-09 17:02 [PATCH v3 0/4] mmc: meson-gx: honour the busy timeout for R1b commands Igor Velkov via B4 Relay
  2026-10-09 17:02 ` [PATCH v3 1/4] mmc: meson-gx: name the limit of the CMD_CFG timeout field Igor Velkov via B4 Relay
@ 2026-10-09 17:02 ` Igor Velkov via B4 Relay
  2026-10-09 17:02 ` [PATCH v3 3/4] mmc: meson-gx: report busy from DAT0 alone Igor Velkov via B4 Relay
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Igor Velkov via B4 Relay @ 2026-10-09 17:02 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
	linux-mmc, linux-amlogic, linux-arm-kernel, linux-kernel,
	Igor Velkov

From: Igor Velkov <iav@iav.lv>

For a command without data the driver programs a fixed 1024 ms into the
CMD_CFG timeout field, and for R1b the controller waits for the card to
release busy within that time. The core sends erase and cache flush as
R1b with busy timeouts of up to 60 s and 30 s, and the controller gives
up after one second:

  mmc_erase: erase error -110, status 0x0
  mmc1: cache flush error -110

Program the timeout from cmd->busy_timeout, kept between 1024 ms, the
fixed value until now, and 32768 ms, the most the field holds, and
rounded up to a power of two. The clamp comes first: MMC_IOC_CMD passes
cmd_timeout_ms from user space straight into busy_timeout, and
roundup_pow_of_two() of a value above 2^31 does not fit in unsigned
int. sdhci takes its command timeout from cmd->busy_timeout in the
same way.

Fixes: 51c5d8447bd7 ("MMC: meson: initial support for GX platforms")
Assisted-by: LLM
Signed-off-by: Igor Velkov <iav@iav.lv>
---
 drivers/mmc/host/meson-gx-mmc.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index 06479ba38525..dd246ad63653 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -216,6 +216,20 @@ static unsigned int meson_mmc_get_timeout_msecs(struct mmc_data *data)
 	return min_t(unsigned int, timeout, SD_EMMC_CMD_TIMEOUT_MAX);
 }
 
+/* For R1b the controller waits for busy to be released within this timeout. */
+static unsigned int meson_mmc_get_cmd_timeout_msecs(struct mmc_command *cmd)
+{
+	unsigned int timeout = cmd->busy_timeout;
+
+	if (!timeout)
+		return SD_EMMC_CMD_TIMEOUT;
+
+	timeout = clamp_t(unsigned int, timeout, SD_EMMC_CMD_TIMEOUT,
+			  SD_EMMC_CMD_TIMEOUT_MAX);
+
+	return roundup_pow_of_two(timeout);
+}
+
 static struct mmc_command *meson_mmc_get_next_command(struct mmc_command *cmd)
 {
 	if (cmd->opcode == MMC_SET_BLOCK_COUNT && !cmd->error)
@@ -842,7 +856,7 @@ static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
 		cmd_data = host->bounce_dma_addr & CMD_DATA_MASK;
 	} else {
 		cmd_cfg |= FIELD_PREP(CMD_CFG_TIMEOUT_MASK,
-				      ilog2(SD_EMMC_CMD_TIMEOUT));
+				      ilog2(meson_mmc_get_cmd_timeout_msecs(cmd)));
 	}
 
 	/* Last descriptor */

-- 
2.43.0



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

* [PATCH v3 3/4] mmc: meson-gx: report busy from DAT0 alone
  2026-10-09 17:02 [PATCH v3 0/4] mmc: meson-gx: honour the busy timeout for R1b commands Igor Velkov via B4 Relay
  2026-10-09 17:02 ` [PATCH v3 1/4] mmc: meson-gx: name the limit of the CMD_CFG timeout field Igor Velkov via B4 Relay
  2026-10-09 17:02 ` [PATCH v3 2/4] mmc: meson-gx: honour the busy timeout for R1b commands Igor Velkov via B4 Relay
@ 2026-10-09 17:02 ` Igor Velkov via B4 Relay
  2026-10-09 17:03 ` [PATCH v3 4/4] mmc: meson-gx: report the longest busy wait the controller can do Igor Velkov via B4 Relay
  2026-10-12  9:23 ` [PATCH v3 0/4] mmc: meson-gx: honour the busy timeout for R1b commands Neil Armstrong
  4 siblings, 0 replies; 6+ messages in thread
From: Igor Velkov via B4 Relay @ 2026-10-09 17:02 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
	linux-mmc, linux-amlogic, linux-arm-kernel, linux-kernel,
	Igor Velkov

From: Igor Velkov <iav@iav.lv>

meson_mmc_card_busy() reports busy only while DAT0..3 are all low. A
busy card drives DAT0 low and leaves DAT1..3 to the pull-ups, and the
callback is defined as "Check if the card is pulling dat[0] low". So a
busy card is reported free, and the core, which prefers card_busy over
CMD13 in mmc_busy_cb(), stops polling after CMD6 and erase at once. The
controller hides this on R1b commands, where it waits for busy itself.
Once max_busy_timeout is reported, the core sends the longer waits, the
120 s BKOPS and 240 s sanitize switches among them, as R1 and has only
the polling left.

Look at DAT0 only, as sdhci_card_busy() does. The checks around the
voltage switch in mmc_set_uhs_voltage() still hold: the card drives
DAT0..3 low together after CMD11 and keeps them low together on
failure.

Fixes: 186cd8b7f586 ("mmc: meson-gx: implement card_busy callback")
Assisted-by: LLM
Signed-off-by: Igor Velkov <iav@iav.lv>
---
 drivers/mmc/host/meson-gx-mmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index dd246ad63653..abdb12e5f997 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -1095,8 +1095,8 @@ static int meson_mmc_card_busy(struct mmc_host *mmc)
 
 	regval = readl(host->regs + SD_EMMC_STATUS);
 
-	/* We are only interrested in lines 0 to 3, so mask the other ones */
-	return !(FIELD_GET(STATUS_DATI, regval) & 0xf);
+	/* The card signals busy on DAT0 alone. */
+	return !(FIELD_GET(STATUS_DATI, regval) & BIT(0));
 }
 
 static int meson_mmc_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)

-- 
2.43.0



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

* [PATCH v3 4/4] mmc: meson-gx: report the longest busy wait the controller can do
  2026-10-09 17:02 [PATCH v3 0/4] mmc: meson-gx: honour the busy timeout for R1b commands Igor Velkov via B4 Relay
                   ` (2 preceding siblings ...)
  2026-10-09 17:02 ` [PATCH v3 3/4] mmc: meson-gx: report busy from DAT0 alone Igor Velkov via B4 Relay
@ 2026-10-09 17:03 ` Igor Velkov via B4 Relay
  2026-10-12  9:23 ` [PATCH v3 0/4] mmc: meson-gx: honour the busy timeout for R1b commands Neil Armstrong
  4 siblings, 0 replies; 6+ messages in thread
From: Igor Velkov via B4 Relay @ 2026-10-09 17:03 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
	linux-mmc, linux-amlogic, linux-arm-kernel, linux-kernel,
	Igor Velkov

From: Igor Velkov <iav@iav.lv>

The driver does not set max_busy_timeout, so the core takes the host
for one that can wait for busy indefinitely and sends erase and cache
flush as R1b with busy timeouts of up to 60 s and 30 s. The CMD_CFG
timeout field holds at most 32768 ms, so the controller times out first.

Report 32768 ms as max_busy_timeout. The core then sizes discards to
fit and, for a longer wait, sends R1 and polls for busy itself.

Fixes: 51c5d8447bd7 ("MMC: meson: initial support for GX platforms")
Assisted-by: LLM
Signed-off-by: Igor Velkov <iav@iav.lv>
---
 drivers/mmc/host/meson-gx-mmc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index abdb12e5f997..49df33bbd8e5 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -1183,6 +1183,9 @@ static int meson_mmc_probe(struct platform_device *pdev)
 
 	mmc->caps |= MMC_CAP_CMD23;
 
+	/* The longest busy wait the CMD_CFG timeout field can hold. */
+	mmc->max_busy_timeout = SD_EMMC_CMD_TIMEOUT_MAX;
+
 	if (mmc->caps & MMC_CAP_SDIO_IRQ)
 		mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
 

-- 
2.43.0



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

* Re: [PATCH v3 0/4] mmc: meson-gx: honour the busy timeout for R1b commands
  2026-10-09 17:02 [PATCH v3 0/4] mmc: meson-gx: honour the busy timeout for R1b commands Igor Velkov via B4 Relay
                   ` (3 preceding siblings ...)
  2026-10-09 17:03 ` [PATCH v3 4/4] mmc: meson-gx: report the longest busy wait the controller can do Igor Velkov via B4 Relay
@ 2026-10-12  9:23 ` Neil Armstrong
  4 siblings, 0 replies; 6+ messages in thread
From: Neil Armstrong @ 2026-10-12  9:23 UTC (permalink / raw)
  To: iav, Ulf Hansson
  Cc: Kevin Hilman, Jerome Brunet, Martin Blumenstingl, linux-mmc,
	linux-amlogic, linux-arm-kernel, linux-kernel

On 10/9/26 19:02, Igor Velkov via B4 Relay wrote:
> For a command without data the driver programs a fixed 1024 ms into the
> CMD_CFG timeout field and does not tell the core how long the controller
> can wait for busy. Erase and cache flush then fail with -110 on eMMC.
> Patch 3 fixes card_busy, which reported a busy card free; patch 4 makes
> the core rely on it.
> 
> Tested on ODROID-N2+ (S922X), 256 GB eMMC, btrfs root with discard=async,
> Armbian builds in docker as load. Without the series (7.3-rc6): 262
> errors in 3 h and 68 in 2.5 h in two runs; the first came 4 and 43 min
> into the build. With v1 (7.3-rc6): 0 in 16 h, 2.4 h of it under the
> build. With v3: 0 in a 37 min kernel build and in a 20 GiB write +
> fstrim; a sanitize went out as R1 and the core polled DAT0 for 523 ms
> until the card was back in TRAN. On 7.1 with the previous eMMC module
> a synthetic test (20 GiB write + fstrim) gave 48 errors without the
> patches, 0 and 0 with them.
> 
> ODROID-N2 (S922X), 128 GB Kingston eMMC, 20 GiB write + fstrim:
> without the series an erase hit the 1024 ms limit and failed with -110
> in 3 of 3 runs. With v3, in 3 such runs and a fill of the card to 85 %
> with rm + fstrim, 5 erases took over 1024 ms, up to 1219 ms, and
> completed; 0 errors.
> 
> ODROID-HC4, SD card in SDR104 at 1.8 V: 0 errors in 5 boots.
> 
> The timeout is rounded up to a power of two: the field holds powers of
> two only, and the timeout is a lower bound. MMC_CAP_WAIT_WHILE_BUSY is
> not set: I have not checked that the controller waits for busy on every
> R1b command, HS400 switches included.
> 
> ---
> Changes in v3:
> - Clamp cmd->busy_timeout to the range of the field before rounding it
>    up to a power of two: the rounding of a value above 2^31 overflowed
>    unsigned int (Sashiko).
> - New patch 3: card_busy reports busy from DAT0 alone. It required
>    DAT0..3 all low and reported a busy card free (Sashiko).
> - Link to v2: https://lore.kernel.org/r/20261008-meson-gx-busy-timeout-v2-0-8bde1adfb5b4@iav.lv
> 
> Changes in v2:
> - Split into three patches, as Neil asked: name the limit of the
>    timeout field, program the R1b timeout from cmd->busy_timeout, report
>    max_busy_timeout.
> - Link to v1: https://lore.kernel.org/r/20261008-meson-gx-busy-timeout-v1-1-d92f3c68c409@iav.lv
> 
> ---
> Igor Velkov (4):
>        mmc: meson-gx: name the limit of the CMD_CFG timeout field
>        mmc: meson-gx: honour the busy timeout for R1b commands
>        mmc: meson-gx: report busy from DAT0 alone
>        mmc: meson-gx: report the longest busy wait the controller can do
> 
>   drivers/mmc/host/meson-gx-mmc.c | 26 ++++++++++++++++++++++----
>   1 file changed, 22 insertions(+), 4 deletions(-)
> ---
> base-commit: fd9af27f6c2319713bb23832066585f8a59a1771
> change-id: 20261005-meson-gx-busy-timeout-7e8e3fdcb3e3
> 
> Best regards,

This looks much better!

For me it looks all good, so:
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>

Thanks,
Neil

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

end of thread, other threads:[~2026-10-12  9:23 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-09 17:02 [PATCH v3 0/4] mmc: meson-gx: honour the busy timeout for R1b commands Igor Velkov via B4 Relay
2026-10-09 17:02 ` [PATCH v3 1/4] mmc: meson-gx: name the limit of the CMD_CFG timeout field Igor Velkov via B4 Relay
2026-10-09 17:02 ` [PATCH v3 2/4] mmc: meson-gx: honour the busy timeout for R1b commands Igor Velkov via B4 Relay
2026-10-09 17:02 ` [PATCH v3 3/4] mmc: meson-gx: report busy from DAT0 alone Igor Velkov via B4 Relay
2026-10-09 17:03 ` [PATCH v3 4/4] mmc: meson-gx: report the longest busy wait the controller can do Igor Velkov via B4 Relay
2026-10-12  9:23 ` [PATCH v3 0/4] mmc: meson-gx: honour the busy timeout for R1b commands Neil Armstrong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®