summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Kerello <christophe.kerello@foss.st.com>2025-08-12 15:55:26 +0200
committerPatrice Chotard <patrice.chotard@foss.st.com>2025-08-25 16:47:39 +0200
commit1067d2060ff017fb58758c0c21ae35504d144ea7 (patch)
tree5ed67e70b3c234c0646098584fed7d41e08758c1
parent4c28c4d9a3a814cebb93e20842ed2c1c90f703d3 (diff)
mmc: stm32_sdmmc2: avoid infinite while loop
Avoid unlimited while loop by adding a timeout. The timeout is calculated based on a minimal throughput of 256 KB/s. The timeout is set at least to 2 seconds. Signed-off-by: Christophe Kerello <christophe.kerello@foss.st.com> Reviewed-by: Patrice Chotard <patrice.chotard@foss.st.com>
-rw-r--r--drivers/mmc/stm32_sdmmc2.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c
index 9483fb57daf..122690aef3e 100644
--- a/drivers/mmc/stm32_sdmmc2.c
+++ b/drivers/mmc/stm32_sdmmc2.c
@@ -385,15 +385,29 @@ static int stm32_sdmmc2_end_data(struct udevice *dev,
u32 mask = SDMMC_STA_DCRCFAIL | SDMMC_STA_DTIMEOUT |
SDMMC_STA_IDMATE | SDMMC_STA_DATAEND;
u32 status;
+ unsigned long timeout_msecs = ctx->data_length >> 8;
+ unsigned long start_timeout;
+
+ /* At least, a timeout of 2 seconds is set */
+ if (timeout_msecs < 2000)
+ timeout_msecs = 2000;
if (data->flags & MMC_DATA_READ)
mask |= SDMMC_STA_RXOVERR;
else
mask |= SDMMC_STA_TXUNDERR;
+ start_timeout = get_timer(0);
status = readl(plat->base + SDMMC_STA);
- while (!(status & mask))
+ while (!(status & mask)) {
+ if (get_timer(start_timeout) > timeout_msecs) {
+ ctx->dpsm_abort = true;
+ return -ETIMEDOUT;
+ }
+
+ schedule();
status = readl(plat->base + SDMMC_STA);
+ }
/*
* Need invalidate the dcache again to avoid any