[PATCH] mmc: tmio: Check INFO1 for completion during DMA transfer

In case a CRC error occurs during DMA transfer, the transfer completion flag is not set in TMIO_SD_DMA_INFO1 and the transfer would eventually time out. The timeout could be very long in case the transfer consists of a large amount of blocks, the base timeout is 10 seconds and every block adds 100 us more.
In case a CRC error does occur, a completion flag is set in a different register, TMIO_SD_INFO1. Use this other completion flag to detect DMA transfer ended and stop waiting for TMIO_SD_DMA_INFO1 completion flag. This reduces the lengthy timeout in case of an error. The unconditional check of TMIO_SD_DMA_INFO2 register for DMA related errors must not be skipped in any case to actually recognize the DMA error and report it.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org --- Cc: Hai Pham hai.pham.ud@renesas.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Paul Barker paul.barker.ct@bp.renesas.com Cc: Peng Fan peng.fan@nxp.com Cc: Sean Anderson seanga2@gmail.com Cc: Tom Rini trini@konsulko.com Cc: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com --- drivers/mmc/tmio-common.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 890c496b535..719c4830bc3 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -299,7 +299,13 @@ static int tmio_sd_dma_wait_for_irq(struct udevice *dev, u32 flag, struct tmio_sd_priv *priv = dev_get_priv(dev); long wait = 1000000 + 10 * blocks;
- while (!(tmio_sd_readl(priv, TMIO_SD_DMA_INFO1) & flag)) { + for (;;) { + if (tmio_sd_readl(priv, TMIO_SD_DMA_INFO1) & flag) + break; + + if (tmio_sd_readl(priv, TMIO_SD_INFO1) & TMIO_SD_INFO1_CMP) + break; + if (wait-- < 0) { dev_err(dev, "timeout during DMA\n"); return -ETIMEDOUT;

On 20/02/2024 08:38, Marek Vasut wrote:
In case a CRC error occurs during DMA transfer, the transfer completion flag is not set in TMIO_SD_DMA_INFO1 and the transfer would eventually time out. The timeout could be very long in case the transfer consists of a large amount of blocks, the base timeout is 10 seconds and every block adds 100 us more.
In case a CRC error does occur, a completion flag is set in a different register, TMIO_SD_INFO1. Use this other completion flag to detect DMA transfer ended and stop waiting for TMIO_SD_DMA_INFO1 completion flag. This reduces the lengthy timeout in case of an error. The unconditional check of TMIO_SD_DMA_INFO2 register for DMA related errors must not be skipped in any case to actually recognize the DMA error and report it.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Hai Pham hai.pham.ud@renesas.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Paul Barker paul.barker.ct@bp.renesas.com Cc: Peng Fan peng.fan@nxp.com Cc: Sean Anderson seanga2@gmail.com Cc: Tom Rini trini@konsulko.com Cc: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com
drivers/mmc/tmio-common.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 890c496b535..719c4830bc3 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -299,7 +299,13 @@ static int tmio_sd_dma_wait_for_irq(struct udevice *dev, u32 flag, struct tmio_sd_priv *priv = dev_get_priv(dev); long wait = 1000000 + 10 * blocks;
- while (!(tmio_sd_readl(priv, TMIO_SD_DMA_INFO1) & flag)) {
- for (;;) {
if (tmio_sd_readl(priv, TMIO_SD_DMA_INFO1) & flag)
break;
if (tmio_sd_readl(priv, TMIO_SD_INFO1) & TMIO_SD_INFO1_CMP)
break;
- if (wait-- < 0) { dev_err(dev, "timeout during DMA\n"); return -ETIMEDOUT;
Reviewed-by: Paul Barker paul.barker.ct@bp.renesas.com Tested-by: Paul Barker paul.barker.ct@bp.renesas.com (tested on RZ/G2L with commit ad50a8151387 from https://source.denx.de/u-boot/custodians/u-boot-sh)

On 2/20/24 17:38, Marek Vasut wrote:
In case a CRC error occurs during DMA transfer, the transfer completion flag is not set in TMIO_SD_DMA_INFO1 and the transfer would eventually time out. The timeout could be very long in case the transfer consists of a large amount of blocks, the base timeout is 10 seconds and every block adds 100 us more.
In case a CRC error does occur, a completion flag is set in a different register, TMIO_SD_INFO1. Use this other completion flag to detect DMA transfer ended and stop waiting for TMIO_SD_DMA_INFO1 completion flag. This reduces the lengthy timeout in case of an error. The unconditional check of TMIO_SD_DMA_INFO2 register for DMA related errors must not be skipped in any case to actually recognize the DMA error and report it.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org Reviewed-by: Paul Barker paul.barker.ct@bp.renesas.com Tested-by: Paul Barker paul.barker.ct@bp.renesas.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Sorry for late. Will apply to u-boot-mmc/master, Thanks!
Best Regards, Jaehoon Chung
Cc: Hai Pham hai.pham.ud@renesas.com Cc: Jaehoon Chung jh80.chung@samsung.com Cc: Nobuhiro Iwamatsu iwamatsu@nigauri.org Cc: Paul Barker paul.barker.ct@bp.renesas.com Cc: Peng Fan peng.fan@nxp.com Cc: Sean Anderson seanga2@gmail.com Cc: Tom Rini trini@konsulko.com Cc: Yoshihiro Shimoda yoshihiro.shimoda.uh@renesas.com
drivers/mmc/tmio-common.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 890c496b535..719c4830bc3 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -299,7 +299,13 @@ static int tmio_sd_dma_wait_for_irq(struct udevice *dev, u32 flag, struct tmio_sd_priv *priv = dev_get_priv(dev); long wait = 1000000 + 10 * blocks;
- while (!(tmio_sd_readl(priv, TMIO_SD_DMA_INFO1) & flag)) {
- for (;;) {
if (tmio_sd_readl(priv, TMIO_SD_DMA_INFO1) & flag)
break;
if (tmio_sd_readl(priv, TMIO_SD_INFO1) & TMIO_SD_INFO1_CMP)
break;
- if (wait-- < 0) { dev_err(dev, "timeout during DMA\n"); return -ETIMEDOUT;
participants (3)
-
Jaehoon Chung
-
Marek Vasut
-
Paul Barker