* [PATCH v2 1/6] mtd: rawnand: gpmi: terminate the DMA chain on completion timeout
2026-10-30 16:20 [PATCH v2 0/6] mtd: nand: stop DMA before unmapping on error and timeout paths Samarth Narang
@ 2026-10-30 16:20 ` Samarth Narang
2026-10-30 16:20 ` [PATCH v2 2/6] mtd: nand: qpic_common: terminate DMA channels on transfer timeout Samarth Narang
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Samarth Narang @ 2026-10-30 16:20 UTC (permalink / raw)
To: Miquel Raynal, Vignesh Raghavendra, Han Xu, Manivannan Sadhasivam,
Maxime Coquelin, Alexandre Torgue
Cc: Richard Weinberger, linux-mtd, imx, linux-arm-msm, linux-stm32,
linux-arm-kernel, linux-kernel, Samarth Narang
When DMA completion times out in gpmi_nfc_exec_op(), the driver unmaps
the operation's buffers and returns -ETIMEDOUT without stopping the APBH
DMA channel. Since mxs-dma leaves the channel in DMA_IN_PROGRESS, the
pending descriptor chain may resume after the timeout, while a
subsequent operation can append new descriptors to the stale chain and
cause the old DATA_IN transfer to execute again against an unmapped
buffer.
This can result in DMA writes to memory that has already been released,
including buffers freed after ONFI parameter page detection in
nand_onfi_detect().
Terminate the channel with dmaengine_terminate_sync() before unmapping
so that outstanding transfers are stopped and subsequent operations
begin with a fresh descriptor chain.
Fixes: ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op")
Assisted-by: LLM
Signed-off-by: Samarth Narang <samarth.colleges@gmail.com>
---
drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 527165ccc..86163a552 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -2659,6 +2659,7 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
if (!to) {
dev_err(this->dev, "DMA timeout, last DMA\n");
gpmi_dump_info(this);
+ dmaengine_terminate_sync(get_dma_chan(this));
ret = -ETIMEDOUT;
goto unmap;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 2/6] mtd: nand: qpic_common: terminate DMA channels on transfer timeout
2026-10-30 16:20 [PATCH v2 0/6] mtd: nand: stop DMA before unmapping on error and timeout paths Samarth Narang
2026-10-30 16:20 ` [PATCH v2 1/6] mtd: rawnand: gpmi: terminate the DMA chain on completion timeout Samarth Narang
@ 2026-10-30 16:20 ` Samarth Narang
2026-10-30 16:20 ` [PATCH v2 3/6] mtd: rawnand: stm32_fmc2: retire data DMA before unmapping on errors Samarth Narang
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Samarth Narang @ 2026-10-30 16:20 UTC (permalink / raw)
To: Miquel Raynal, Vignesh Raghavendra, Han Xu, Manivannan Sadhasivam,
Maxime Coquelin, Alexandre Torgue
Cc: Richard Weinberger, linux-mtd, imx, linux-arm-msm, linux-stm32,
linux-arm-kernel, linux-kernel, Samarth Narang
When DMA completion times out in qcom_submit_descs(), the driver unmaps
the descriptors' scatterlists without stopping the BAM DMA channels.
Since the issued descriptors may still be active, the RX and TX channels
can continue accessing the caller's buffer after it has been unmapped
and returned to the NAND core. The ADM path has a similar issue when
dma_sync_wait() times out.
Terminate the affected channels with dmaengine_terminate_sync() before
unmapping, ensuring that outstanding DMA transfers are stopped before
their mappings are released. On BAM, termination resets the pipe and
discards pending descriptors.
Fixes: 381dd24539a8 ("mtd: nand: qcom: add BAM DMA descriptor handling")
Fixes: c76b78d8ec05 ("mtd: nand: Qualcomm NAND controller driver")
Assisted-by: LLM
Signed-off-by: Samarth Narang <samarth.colleges@gmail.com>
---
drivers/mtd/nand/qpic_common.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/qpic_common.c b/drivers/mtd/nand/qpic_common.c
index 4f3e4dd76..250154a08 100644
--- a/drivers/mtd/nand/qpic_common.c
+++ b/drivers/mtd/nand/qpic_common.c
@@ -592,11 +592,18 @@ int qcom_submit_descs(struct qcom_nand_controller *nandc)
dma_async_issue_pending(nandc->cmd_chan);
if (!wait_for_completion_timeout(&bam_txn->txn_done,
- QPIC_NAND_COMPLETION_TIMEOUT))
+ QPIC_NAND_COMPLETION_TIMEOUT)) {
+ /* Retire every issued pipe before unmapping its buffers. */
+ dmaengine_terminate_sync(nandc->tx_chan);
+ dmaengine_terminate_sync(nandc->rx_chan);
+ dmaengine_terminate_sync(nandc->cmd_chan);
ret = -ETIMEDOUT;
+ }
} else {
- if (dma_sync_wait(nandc->chan, cookie) != DMA_COMPLETE)
+ if (dma_sync_wait(nandc->chan, cookie) != DMA_COMPLETE) {
+ dmaengine_terminate_sync(nandc->chan);
ret = -ETIMEDOUT;
+ }
}
err_unmap_free_desc:
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 3/6] mtd: rawnand: stm32_fmc2: retire data DMA before unmapping on errors
2026-10-30 16:20 [PATCH v2 0/6] mtd: nand: stop DMA before unmapping on error and timeout paths Samarth Narang
2026-10-30 16:20 ` [PATCH v2 1/6] mtd: rawnand: gpmi: terminate the DMA chain on completion timeout Samarth Narang
2026-10-30 16:20 ` [PATCH v2 2/6] mtd: nand: qpic_common: terminate DMA channels on transfer timeout Samarth Narang
@ 2026-10-30 16:20 ` Samarth Narang
2026-10-30 16:20 ` [PATCH v2 4/6] mtd: rawnand: omap2: terminate DMA when prefetch cannot be enabled Samarth Narang
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Samarth Narang @ 2026-10-30 16:20 UTC (permalink / raw)
To: Miquel Raynal, Vignesh Raghavendra, Han Xu, Manivannan Sadhasivam,
Maxime Coquelin, Alexandre Torgue
Cc: Richard Weinberger, linux-mtd, imx, linux-arm-msm, linux-stm32,
linux-arm-kernel, linux-kernel, Samarth Narang
When ECC descriptor preparation or submission fails in
stm32_fmc2_nfc_xfer(), the driver unmaps the data scatterlist without
terminating the previously issued DMA descriptor. The descriptor may
remain queued and execute when the next page operation starts,
potentially writing into a buffer that has already been unmapped and
returned to the NAND core. The timeout paths have a similar issue, as
they use dmaengine_terminate_all(), which does not guarantee that DMA
has stopped before the buffer is unmapped.
Terminate the outstanding data descriptor on ECC error paths and use
dmaengine_terminate_sync() on timeout paths, ensuring that DMA has
stopped before the associated mapping is released.
Fixes: 2cd457f328c1 ("mtd: rawnand: stm32_fmc2: add STM32 FMC2 NAND flash controller driver")
Assisted-by: LLM
Signed-off-by: Samarth Narang <samarth.colleges@gmail.com>
---
drivers/mtd/nand/raw/stm32_fmc2_nand.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index c08d6b176..82d630106 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -915,6 +915,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
DMA_PREP_INTERRUPT);
if (!desc_ecc) {
ret = -ENOMEM;
+ dmaengine_terminate_sync(dma_ch);
goto err_unmap_data;
}
@@ -922,8 +923,10 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
desc_ecc->callback = stm32_fmc2_nfc_dma_callback;
desc_ecc->callback_param = &nfc->dma_ecc_complete;
ret = dma_submit_error(dmaengine_submit(desc_ecc));
- if (ret)
+ if (ret) {
+ dmaengine_terminate_sync(dma_ch);
goto err_unmap_data;
+ }
dma_async_issue_pending(nfc->dma_ecc_ch);
}
@@ -939,9 +942,9 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
if (!wait_for_completion_timeout(&nfc->complete, timeout)) {
dev_err(nfc->dev, "seq timeout\n");
stm32_fmc2_nfc_disable_seq_irq(nfc);
- dmaengine_terminate_all(dma_ch);
+ dmaengine_terminate_sync(dma_ch);
if (!write_data && !raw)
- dmaengine_terminate_all(nfc->dma_ecc_ch);
+ dmaengine_terminate_sync(nfc->dma_ecc_ch);
ret = -ETIMEDOUT;
goto err_unmap_data;
}
@@ -949,7 +952,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
/* Wait DMA data transfer completion */
if (!wait_for_completion_timeout(&nfc->dma_data_complete, timeout)) {
dev_err(nfc->dev, "data DMA timeout\n");
- dmaengine_terminate_all(dma_ch);
+ dmaengine_terminate_sync(dma_ch);
ret = -ETIMEDOUT;
}
@@ -958,7 +961,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
if (!wait_for_completion_timeout(&nfc->dma_ecc_complete,
timeout)) {
dev_err(nfc->dev, "ECC DMA timeout\n");
- dmaengine_terminate_all(nfc->dma_ecc_ch);
+ dmaengine_terminate_sync(nfc->dma_ecc_ch);
ret = -ETIMEDOUT;
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 4/6] mtd: rawnand: omap2: terminate DMA when prefetch cannot be enabled
2026-10-30 16:20 [PATCH v2 0/6] mtd: nand: stop DMA before unmapping on error and timeout paths Samarth Narang
` (2 preceding siblings ...)
2026-10-30 16:20 ` [PATCH v2 3/6] mtd: rawnand: stm32_fmc2: retire data DMA before unmapping on errors Samarth Narang
@ 2026-10-30 16:20 ` Samarth Narang
2026-10-30 16:20 ` [PATCH v2 5/6] mtd: rawnand: marvell: stop DMA before unmapping on timeout Samarth Narang
2026-10-30 16:20 ` [PATCH v2 6/6] mtd: rawnand: sh_flctl: use dmaengine_terminate_sync() on DMA timeout Samarth Narang
5 siblings, 0 replies; 7+ messages in thread
From: Samarth Narang @ 2026-10-30 16:20 UTC (permalink / raw)
To: Miquel Raynal, Vignesh Raghavendra, Han Xu, Manivannan Sadhasivam,
Maxime Coquelin, Alexandre Torgue
Cc: Richard Weinberger, linux-mtd, imx, linux-arm-msm, linux-stm32,
linux-arm-kernel, linux-kernel, Samarth Narang
When omap_prefetch_enable() fails because the prefetch engine is busy,
omap_nand_dma_transfer() unmaps the buffer and falls back to a CPU copy
without terminating the previously issued DMA descriptor. The descriptor
may therefore continue accessing the unmapped buffer, while its callback
could also signal info->comp for a subsequent transfer.
Terminate the DMA channel with dmaengine_terminate_sync() before
unmapping the buffer, ensuring that the outstanding transfer has stopped
before the fallback path proceeds.
Fixes: 03d3a1df6da6 ("mtd: nand: omap2: Start dma request before enabling prefetch")
Assisted-by: LLM
Signed-off-by: Samarth Narang <samarth.colleges@gmail.com>
---
This issue was identified by a research static analyzer for DMA
lifecycle ordering and has not been validated on hardware.
drivers/mtd/nand/raw/omap2.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c
index 552f36da7..b6bd4386c 100644
--- a/drivers/mtd/nand/raw/omap2.c
+++ b/drivers/mtd/nand/raw/omap2.c
@@ -417,9 +417,11 @@ static inline int omap_nand_dma_transfer(struct nand_chip *chip,
/* configure and start prefetch transfer */
ret = omap_prefetch_enable(info->gpmc_cs,
PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write, info);
- if (ret)
+ if (ret) {
/* PFPW engine is busy, use cpu copy method */
+ dmaengine_terminate_sync(info->dma);
goto out_copy_unmap;
+ }
wait_for_completion(&info->comp);
tim = 0;
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 5/6] mtd: rawnand: marvell: stop DMA before unmapping on timeout
2026-10-30 16:20 [PATCH v2 0/6] mtd: nand: stop DMA before unmapping on error and timeout paths Samarth Narang
` (3 preceding siblings ...)
2026-10-30 16:20 ` [PATCH v2 4/6] mtd: rawnand: omap2: terminate DMA when prefetch cannot be enabled Samarth Narang
@ 2026-10-30 16:20 ` Samarth Narang
2026-10-30 16:20 ` [PATCH v2 6/6] mtd: rawnand: sh_flctl: use dmaengine_terminate_sync() on DMA timeout Samarth Narang
5 siblings, 0 replies; 7+ messages in thread
From: Samarth Narang @ 2026-10-30 16:20 UTC (permalink / raw)
To: Miquel Raynal, Vignesh Raghavendra, Han Xu, Manivannan Sadhasivam,
Maxime Coquelin, Alexandre Torgue
Cc: Richard Weinberger, linux-mtd, imx, linux-arm-msm, linux-stm32,
linux-arm-kernel, linux-kernel, Samarth Narang
When marvell_nfc_wait_cmdd() times out in marvell_nfc_xfer_data_dma(),
the driver unmaps the DMA buffer before calling
dmaengine_terminate_all(), which does not guarantee that the transfer
has stopped. As a result, the DMA engine may continue accessing the
buffer after its mapping has been released.
Use dmaengine_terminate_sync() before unmapping the buffer on the
timeout path, while preserving the existing status logging before
termination so that it reflects the timed-out transfer.
Fixes: 02f26ecf8c77 ("mtd: nand: add reworked Marvell NAND controller driver")
Assisted-by: LLM
Signed-off-by: Samarth Narang <samarth.colleges@gmail.com>
---
This issue was identified by a research static analyzer for DMA
lifecycle ordering and has not been validated on hardware.
drivers/mtd/nand/raw/marvell_nand.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
index 38b7eb5b9..a342a48e2 100644
--- a/drivers/mtd/nand/raw/marvell_nand.c
+++ b/drivers/mtd/nand/raw/marvell_nand.c
@@ -900,14 +900,15 @@ static int marvell_nfc_xfer_data_dma(struct marvell_nfc *nfc,
dma_async_issue_pending(nfc->dma_chan);
ret = marvell_nfc_wait_cmdd(nfc->selected_chip);
- dma_unmap_sg(nfc->dma_chan->device->dev, &sg, 1, direction);
- marvell_nfc_disable_dma(nfc);
if (ret) {
dev_err(nfc->dev, "Timeout waiting for DMA (status: %d)\n",
dmaengine_tx_status(nfc->dma_chan, cookie, NULL));
- dmaengine_terminate_all(nfc->dma_chan);
- return -ETIMEDOUT;
+ dmaengine_terminate_sync(nfc->dma_chan);
}
+ dma_unmap_sg(nfc->dma_chan->device->dev, &sg, 1, direction);
+ marvell_nfc_disable_dma(nfc);
+ if (ret)
+ return -ETIMEDOUT;
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 6/6] mtd: rawnand: sh_flctl: use dmaengine_terminate_sync() on DMA timeout
2026-10-30 16:20 [PATCH v2 0/6] mtd: nand: stop DMA before unmapping on error and timeout paths Samarth Narang
` (4 preceding siblings ...)
2026-10-30 16:20 ` [PATCH v2 5/6] mtd: rawnand: marvell: stop DMA before unmapping on timeout Samarth Narang
@ 2026-10-30 16:20 ` Samarth Narang
5 siblings, 0 replies; 7+ messages in thread
From: Samarth Narang @ 2026-10-30 16:20 UTC (permalink / raw)
To: Miquel Raynal, Vignesh Raghavendra, Han Xu, Manivannan Sadhasivam,
Maxime Coquelin, Alexandre Torgue
Cc: Richard Weinberger, linux-mtd, imx, linux-arm-msm, linux-stm32,
linux-arm-kernel, linux-kernel, Samarth Narang
When DMA completion times out in flctl_dma_fifo0_transfer(), the driver
calls dmaengine_terminate_all() before unmapping the buffer. Since this
does not guarantee that the transfer has stopped, the DMA engine may
continue accessing memory after its mapping has been released.
Replace dmaengine_terminate_all() with dmaengine_terminate_sync() to
ensure that DMA has stopped before unmapping the buffer, which is safe
because the function already sleeps while waiting for completion.
Fixes: 83738d87e3a0 ("mtd: sh_flctl: Add DMA capabilty")
Assisted-by: LLM
Signed-off-by: Samarth Narang <samarth.colleges@gmail.com>
---
This issue was identified by a research static analyzer for DMA
lifecycle ordering and has not been validated on hardware.
drivers/mtd/nand/raw/sh_flctl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c
index 97f733e48..8bf9ae7ce 100644
--- a/drivers/mtd/nand/raw/sh_flctl.c
+++ b/drivers/mtd/nand/raw/sh_flctl.c
@@ -430,7 +430,7 @@ static int flctl_dma_fifo0_transfer(struct sh_flctl *flctl, unsigned long *buf,
msecs_to_jiffies(3000));
if (time_left == 0) {
- dmaengine_terminate_all(chan);
+ dmaengine_terminate_sync(chan);
dev_err(&flctl->pdev->dev, "wait_for_completion_timeout\n");
ret = -ETIMEDOUT;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread