From e29e650077e01dddf69bc8fac31e0cd60043aa7c Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Tue, 23 Jun 2026 14:11:12 +0800 Subject: [PATCH] mmc: moxart: report DMA completion timeout moxart_transfer_dma() waits for the DMA completion but ignores wait_for_completion_interruptible_timeout(). It then unconditionally reports the full transfer length in data->bytes_xfered. Terminate the DMA channel and set data->error when the wait is interrupted or times out. Only report host->data_len as transferred after the completion is observed. Signed-off-by: Pengpeng Hou Signed-off-by: Ulf Hansson --- drivers/mmc/host/moxart-mmc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c index 3dd8f232052f..4a4d8b19b18c 100644 --- a/drivers/mmc/host/moxart-mmc.c +++ b/drivers/mmc/host/moxart-mmc.c @@ -264,6 +264,7 @@ static void moxart_transfer_dma(struct mmc_data *data, struct moxart_host *host) u32 len, dir_slave; struct dma_async_tx_descriptor *desc = NULL; struct dma_chan *dma_chan; + long timeout; if (host->data_len == data->bytes_xfered) return; @@ -296,11 +297,17 @@ static void moxart_transfer_dma(struct mmc_data *data, struct moxart_host *host) dma_async_issue_pending(dma_chan); } - wait_for_completion_interruptible_timeout(&host->dma_complete, - host->timeout); + timeout = wait_for_completion_interruptible_timeout(&host->dma_complete, + host->timeout); + if (timeout <= 0) { + dmaengine_terminate_sync(dma_chan); + data->error = timeout ?: -ETIMEDOUT; + goto unmap; + } data->bytes_xfered = host->data_len; +unmap: dma_unmap_sg(dma_chan->device->dev, data->sg, data->sg_len, mmc_get_dma_dir(data));