[PATCH] mtd: rawnand: lpc32xx_mlc: fail DMA transfers on timeout
Pengpeng Hou
pengpeng at iscas.ac.cn
Wed Jun 24 17:33:27 PDT 2026
lpc32xx_xmit_dma() starts a DMA transfer and waits up to one second for
its completion, but it ignores the wait result and returns success after
unmapping the buffer.
A timed out read can therefore return success with incomplete data, and a
timed out write can continue the NAND operation without proof that the DMA
payload reached the controller.
Terminate the DMA channel on timeout, unmap the scatterlist through the
existing cleanup path, and return -ETIMEDOUT to the NAND read/write
callers.
Signed-off-by: Pengpeng Hou <pengpeng at iscas.ac.cn>
---
drivers/mtd/nand/raw/lpc32xx_mlc.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c
index 19b13ae53..8f6a89d9b 100644
--- a/drivers/mtd/nand/raw/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c
@@ -396,6 +396,7 @@ static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len,
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
struct dma_async_tx_descriptor *desc;
int flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+ unsigned long time_left;
int res;
sg_init_one(&host->sgl, mem, len);
@@ -410,6 +411,7 @@ static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len,
flags);
if (!desc) {
dev_err(mtd->dev.parent, "Failed to prepare slave sg\n");
+ res = -ENXIO;
goto out1;
}
@@ -420,7 +422,13 @@ static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len,
dmaengine_submit(desc);
dma_async_issue_pending(host->dma_chan);
- wait_for_completion_timeout(&host->comp_dma, msecs_to_jiffies(1000));
+ time_left = wait_for_completion_timeout(&host->comp_dma,
+ msecs_to_jiffies(1000));
+ if (!time_left) {
+ dmaengine_terminate_sync(host->dma_chan);
+ res = -ETIMEDOUT;
+ goto out1;
+ }
dma_unmap_sg(host->dma_chan->device->dev, &host->sgl, 1,
DMA_BIDIRECTIONAL);
@@ -428,7 +436,7 @@ static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len,
out1:
dma_unmap_sg(host->dma_chan->device->dev, &host->sgl, 1,
DMA_BIDIRECTIONAL);
- return -ENXIO;
+ return res;
}
static int lpc32xx_read_page(struct nand_chip *chip, uint8_t *buf,
--
2.50.1 (Apple Git-155)
More information about the linux-arm-kernel
mailing list