* [PATCH v2 0/2] spi: fsl-lpspi: fix DMA termination issues
@ 2026-05-20 9:43 Carlos Song (OSS)
2026-05-20 9:43 ` [PATCH v2 1/2] spi: fsl-lpspi: replace dmaengine_terminate_all with dmaengine_terminate_sync Carlos Song (OSS)
2026-05-20 9:43 ` [PATCH v2 2/2] spi: fsl-lpspi: fix missing RX DMA termination on TX prepare failure Carlos Song (OSS)
0 siblings, 2 replies; 7+ messages in thread
From: Carlos Song (OSS) @ 2026-05-20 9:43 UTC (permalink / raw)
To: Frank.Li, broonie, xiaoning.wang, Fugang.duan
Cc: linux-spi, imx, linux-kernel, Carlos Song
From: Carlos Song <carlos.song@nxp.com>
This series fixes two issues in the fsl-lpspi DMA transfer error paths.
Patch 1 replaces the deprecated dmaengine_terminate_all() with
dmaengine_terminate_sync() across all error paths in
fsl_lpspi_dma_transfer().
Patch 2 fixes a missing RX DMA channel termination when TX descriptor
preparation fails. Since the RX channel is already submitted and issued
before the TX descriptor is prepared, returning -EINVAL without
terminating the RX channel leaves it running against buffers that the
SPI core will unmap, potentially causing memory corruption.
Carlos Song (2):
spi: fsl-lpspi: replace dmaengine_terminate_all with
dmaengine_terminate_sync
spi: fsl-lpspi: fix missing RX DMA termination on TX prepare failure
drivers/spi/spi-fsl-lpspi.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/2] spi: fsl-lpspi: replace dmaengine_terminate_all with dmaengine_terminate_sync
2026-05-20 9:43 [PATCH v2 0/2] spi: fsl-lpspi: fix DMA termination issues Carlos Song (OSS)
@ 2026-05-20 9:43 ` Carlos Song (OSS)
2026-05-20 10:00 ` sashiko-bot
2026-05-20 16:52 ` Frank Li
2026-05-20 9:43 ` [PATCH v2 2/2] spi: fsl-lpspi: fix missing RX DMA termination on TX prepare failure Carlos Song (OSS)
1 sibling, 2 replies; 7+ messages in thread
From: Carlos Song (OSS) @ 2026-05-20 9:43 UTC (permalink / raw)
To: Frank.Li, broonie, xiaoning.wang, Fugang.duan
Cc: linux-spi, imx, linux-kernel, Carlos Song, stable
From: Carlos Song <carlos.song@nxp.com>
The terminate API dmaengine_terminate_all() has been deprecated, improve
driver with dmaengine_terminate_sync().
Fixes: 09c04466ce7e ("spi: lpspi: add dma mode support")
Cc: stable@vger.kernel.org
Signed-off-by: Carlos Song <carlos.song@nxp.com>
---
Change for V2:
- No change in v2.
---
drivers/spi/spi-fsl-lpspi.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index e201309f8aae..1a94a42fac31 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -647,7 +647,7 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
tx->sgl, tx->nents, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_tx) {
- dmaengine_terminate_all(controller->dma_tx);
+ dmaengine_terminate_sync(controller->dma_tx);
return -EINVAL;
}
@@ -668,8 +668,8 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
transfer_timeout);
if (!time_left) {
dev_err(fsl_lpspi->dev, "I/O Error in DMA TX\n");
- dmaengine_terminate_all(controller->dma_tx);
- dmaengine_terminate_all(controller->dma_rx);
+ dmaengine_terminate_sync(controller->dma_tx);
+ dmaengine_terminate_sync(controller->dma_rx);
fsl_lpspi_reset(fsl_lpspi);
return -ETIMEDOUT;
}
@@ -678,8 +678,8 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
transfer_timeout);
if (!time_left) {
dev_err(fsl_lpspi->dev, "I/O Error in DMA RX\n");
- dmaengine_terminate_all(controller->dma_tx);
- dmaengine_terminate_all(controller->dma_rx);
+ dmaengine_terminate_sync(controller->dma_tx);
+ dmaengine_terminate_sync(controller->dma_rx);
fsl_lpspi_reset(fsl_lpspi);
return -ETIMEDOUT;
}
@@ -688,8 +688,8 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
fsl_lpspi->target_aborted) {
dev_dbg(fsl_lpspi->dev,
"I/O Error in DMA TX interrupted\n");
- dmaengine_terminate_all(controller->dma_tx);
- dmaengine_terminate_all(controller->dma_rx);
+ dmaengine_terminate_sync(controller->dma_tx);
+ dmaengine_terminate_sync(controller->dma_rx);
fsl_lpspi_reset(fsl_lpspi);
return -EINTR;
}
@@ -698,8 +698,8 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
fsl_lpspi->target_aborted) {
dev_dbg(fsl_lpspi->dev,
"I/O Error in DMA RX interrupted\n");
- dmaengine_terminate_all(controller->dma_tx);
- dmaengine_terminate_all(controller->dma_rx);
+ dmaengine_terminate_sync(controller->dma_tx);
+ dmaengine_terminate_sync(controller->dma_rx);
fsl_lpspi_reset(fsl_lpspi);
return -EINTR;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] spi: fsl-lpspi: fix missing RX DMA termination on TX prepare failure
2026-05-20 9:43 [PATCH v2 0/2] spi: fsl-lpspi: fix DMA termination issues Carlos Song (OSS)
2026-05-20 9:43 ` [PATCH v2 1/2] spi: fsl-lpspi: replace dmaengine_terminate_all with dmaengine_terminate_sync Carlos Song (OSS)
@ 2026-05-20 9:43 ` Carlos Song (OSS)
2026-05-20 10:30 ` sashiko-bot
2026-05-20 16:57 ` Frank Li
1 sibling, 2 replies; 7+ messages in thread
From: Carlos Song (OSS) @ 2026-05-20 9:43 UTC (permalink / raw)
To: Frank.Li, broonie, xiaoning.wang, Fugang.duan
Cc: linux-spi, imx, linux-kernel, Carlos Song, stable
From: Carlos Song <carlos.song@nxp.com>
When dmaengine_prep_slave_sg() fails for the TX channel, the error path
only terminates the TX DMA channel but leaves the RX channel running.
Since the RX channel was already submitted and issued prior to preparing
the TX descriptor, returning -EINVAL causes the SPI core to unmap the
DMA buffers while the RX DMA engine continues writing to them, leading
to potential memory corruption or use-after-free.
Fix this by also terminating the RX channel before returning on the TX
prepare failure path.
Fixes: 09c04466ce7e ("spi: lpspi: add dma mode support")
Cc: stable@vger.kernel.org
Signed-off-by: Carlos Song <carlos.song@nxp.com>
---
change for v2:
- Add fix missing RX DMA termination on TX prepare failure.
---
drivers/spi/spi-fsl-lpspi.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
index 1a94a42fac31..906892453a84 100644
--- a/drivers/spi/spi-fsl-lpspi.c
+++ b/drivers/spi/spi-fsl-lpspi.c
@@ -647,6 +647,7 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
tx->sgl, tx->nents, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_tx) {
+ dmaengine_terminate_sync(controller->dma_rx);
dmaengine_terminate_sync(controller->dma_tx);
return -EINVAL;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/2] spi: fsl-lpspi: replace dmaengine_terminate_all with dmaengine_terminate_sync
2026-05-20 9:43 ` [PATCH v2 1/2] spi: fsl-lpspi: replace dmaengine_terminate_all with dmaengine_terminate_sync Carlos Song (OSS)
@ 2026-05-20 10:00 ` sashiko-bot
2026-05-20 16:52 ` Frank Li
1 sibling, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-05-20 10:00 UTC (permalink / raw)
Cc: imx, Frank.Li
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Lockless initialization of `target_aborted` after `reinit_completion` overwrites concurrent aborts, causing missed DMA termination and memory corruption.
--
commit ad3a6e81718f2fdf6938f3f573651fd3ac718677
Author: Carlos Song <carlos.song@nxp.com>
spi: fsl-lpspi: replace dmaengine_terminate_all with dmaengine_terminate_sync
This commit replaces the deprecated dmaengine_terminate_all API with
dmaengine_terminate_sync to improve the fsl-lpspi driver.
> diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
> index e201309f8aae3..1a94a42fac319 100644
> --- a/drivers/spi/spi-fsl-lpspi.c
> +++ b/drivers/spi/spi-fsl-lpspi.c
[ ... ]
> @@ -688,8 +688,8 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
> fsl_lpspi->target_aborted) {
[Severity: High]
This isn't a bug introduced by this patch, but could this target_aborted check
miss concurrent aborts due to a race condition earlier in the function?
In fsl_lpspi_dma_transfer(), the driver locklessly sets
fsl_lpspi->target_aborted = false after reinitializing the completions and
issuing pending DMA transfers.
If the SPI core or a slave protocol driver calls spi_target_abort()
concurrently, the abort handler will set target_aborted = true and signal the
completions.
Thread execution ordering could cause the fsl_lpspi->target_aborted = false
assignment to immediately overwrite the true abort state. When the driver
subsequently waits on the completions here, it consumes the abort signal but
fails this check because the flag evaluates to false.
Since the driver falsely assumes the transfer completed successfully,
it skips calling the dmaengine_terminate_sync() added in this block. The
SPI core would then proceed to unmap the scatterlist buffers while the DMA
is still actively transferring data, which leads to writing into unmapped
or freed memory.
> dev_dbg(fsl_lpspi->dev,
> "I/O Error in DMA TX interrupted\n");
> - dmaengine_terminate_all(controller->dma_tx);
> - dmaengine_terminate_all(controller->dma_rx);
> + dmaengine_terminate_sync(controller->dma_tx);
> + dmaengine_terminate_sync(controller->dma_rx);
> fsl_lpspi_reset(fsl_lpspi);
> return -EINTR;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260520094308.2882892-1-carlos.song@oss.nxp.com?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] spi: fsl-lpspi: fix missing RX DMA termination on TX prepare failure
2026-05-20 9:43 ` [PATCH v2 2/2] spi: fsl-lpspi: fix missing RX DMA termination on TX prepare failure Carlos Song (OSS)
@ 2026-05-20 10:30 ` sashiko-bot
2026-05-20 16:57 ` Frank Li
1 sibling, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-05-20 10:30 UTC (permalink / raw)
Cc: Frank.Li, imx
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] The early error return paths in `fsl_lpspi_dma_transfer()` fail to call `fsl_lpspi_reset()`, leaving the SPI controller enabled with active DMA requests and stale FIFO contents.
- [High] A race condition between asynchronous target aborts and transfer preparation can lead to lost abort signals and indefinite task hangs.
--
commit 28e337398d010b76ae512c9b76eaed6b301c616f
Author: Carlos Song <carlos.song@nxp.com>
spi: fsl-lpspi: fix missing RX DMA termination on TX prepare failure
This commit addresses a potential memory corruption or use-after-free issue
when the TX DMA descriptor fails to prepare. It ensures the RX DMA channel
is also appropriately terminated before returning an error.
> diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
> index 1a94a42fac319..906892453a843 100644
> --- a/drivers/spi/spi-fsl-lpspi.c
> +++ b/drivers/spi/spi-fsl-lpspi.c
> @@ -647,6 +647,7 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
> tx->sgl, tx->nents, DMA_MEM_TO_DEV,
> DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
> if (!desc_tx) {
> + dmaengine_terminate_sync(controller->dma_rx);
> dmaengine_terminate_sync(controller->dma_tx);
> return -EINVAL;
[Severity: High]
This is a pre-existing issue, but does this error path leave the SPI
controller enabled and out of sync?
Prior to calling fsl_lpspi_dma_transfer(), the driver executes
fsl_lpspi_set_cmd() and fsl_lpspi_setup_transfer(). These enable the
SPI module and DMA requests, pushing a command word into the TX FIFO.
If dmaengine_prep_slave_sg() fails for the TX descriptor, we terminate the
DMA channels and return -EINVAL. The caller propagates this error to the
SPI core, but since the spi-fsl-lpspi driver does not implement the
handle_err() callback, the hardware is never reset by the core.
Since fsl_lpspi_reset() is bypassed here, the SPI module remains
enabled. Could subsequent transfers fail or corrupt data, making the
SPI controller unusable until the driver is unbound or the system reboots?
[Severity: High]
This isn't a bug introduced by this patch, but does the transfer preparation
sequence have a race condition with asynchronous target aborts?
fsl_lpspi_target_abort() can be called asynchronously by the SPI target
protocol driver to cancel an ongoing transfer, which sets
target_aborted to true and signals the completion structures.
Shortly after the DMA descriptor preparation shown above, the driver
calls reinit_completion() and unconditionally sets target_aborted to false:
fsl_lpspi_dma_transfer() {
...
reinit_completion(&fsl_lpspi->dma_tx_completion);
dma_async_issue_pending(controller->dma_tx);
fsl_lpspi->target_aborted = false;
...
}
If fsl_lpspi_target_abort() executes just before these variables are reset,
the completion wakeup count is overwritten to 0 and the abort flag is
cleared.
Since target mode transfers use wait_for_completion_interruptible() without
a timeout, would the SPI worker thread block indefinitely waiting for a
transfer that the master has already aborted?
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260520094308.2882892-1-carlos.song@oss.nxp.com?part=2
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/2] spi: fsl-lpspi: replace dmaengine_terminate_all with dmaengine_terminate_sync
2026-05-20 9:43 ` [PATCH v2 1/2] spi: fsl-lpspi: replace dmaengine_terminate_all with dmaengine_terminate_sync Carlos Song (OSS)
2026-05-20 10:00 ` sashiko-bot
@ 2026-05-20 16:52 ` Frank Li
1 sibling, 0 replies; 7+ messages in thread
From: Frank Li @ 2026-05-20 16:52 UTC (permalink / raw)
To: Carlos Song (OSS)
Cc: broonie, xiaoning.wang, Fugang.duan, linux-spi, imx, linux-kernel,
Carlos Song, stable
On Wed, May 20, 2026 at 05:43:07PM +0800, Carlos Song (OSS) wrote:
subject dmaengine_terminate_all() and dmaengine_terminate_sync(),
all function need add ()
> From: Carlos Song <carlos.song@nxp.com>
>
> The terminate API dmaengine_terminate_all() has been deprecated, improve
> driver with dmaengine_terminate_sync().
Nit: replace it with dmaengine_terminate_sync()
Frank
>
> Fixes: 09c04466ce7e ("spi: lpspi: add dma mode support")
> Cc: stable@vger.kernel.org
> Signed-off-by: Carlos Song <carlos.song@nxp.com>
> ---
> Change for V2:
> - No change in v2.
> ---
> drivers/spi/spi-fsl-lpspi.c | 18 +++++++++---------
> 1 file changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
> index e201309f8aae..1a94a42fac31 100644
> --- a/drivers/spi/spi-fsl-lpspi.c
> +++ b/drivers/spi/spi-fsl-lpspi.c
> @@ -647,7 +647,7 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
> tx->sgl, tx->nents, DMA_MEM_TO_DEV,
> DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
> if (!desc_tx) {
> - dmaengine_terminate_all(controller->dma_tx);
> + dmaengine_terminate_sync(controller->dma_tx);
> return -EINVAL;
> }
>
> @@ -668,8 +668,8 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
> transfer_timeout);
> if (!time_left) {
> dev_err(fsl_lpspi->dev, "I/O Error in DMA TX\n");
> - dmaengine_terminate_all(controller->dma_tx);
> - dmaengine_terminate_all(controller->dma_rx);
> + dmaengine_terminate_sync(controller->dma_tx);
> + dmaengine_terminate_sync(controller->dma_rx);
> fsl_lpspi_reset(fsl_lpspi);
> return -ETIMEDOUT;
> }
> @@ -678,8 +678,8 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
> transfer_timeout);
> if (!time_left) {
> dev_err(fsl_lpspi->dev, "I/O Error in DMA RX\n");
> - dmaengine_terminate_all(controller->dma_tx);
> - dmaengine_terminate_all(controller->dma_rx);
> + dmaengine_terminate_sync(controller->dma_tx);
> + dmaengine_terminate_sync(controller->dma_rx);
> fsl_lpspi_reset(fsl_lpspi);
> return -ETIMEDOUT;
> }
> @@ -688,8 +688,8 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
> fsl_lpspi->target_aborted) {
> dev_dbg(fsl_lpspi->dev,
> "I/O Error in DMA TX interrupted\n");
> - dmaengine_terminate_all(controller->dma_tx);
> - dmaengine_terminate_all(controller->dma_rx);
> + dmaengine_terminate_sync(controller->dma_tx);
> + dmaengine_terminate_sync(controller->dma_rx);
> fsl_lpspi_reset(fsl_lpspi);
> return -EINTR;
> }
> @@ -698,8 +698,8 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
> fsl_lpspi->target_aborted) {
> dev_dbg(fsl_lpspi->dev,
> "I/O Error in DMA RX interrupted\n");
> - dmaengine_terminate_all(controller->dma_tx);
> - dmaengine_terminate_all(controller->dma_rx);
> + dmaengine_terminate_sync(controller->dma_tx);
> + dmaengine_terminate_sync(controller->dma_rx);
> fsl_lpspi_reset(fsl_lpspi);
> return -EINTR;
> }
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] spi: fsl-lpspi: fix missing RX DMA termination on TX prepare failure
2026-05-20 9:43 ` [PATCH v2 2/2] spi: fsl-lpspi: fix missing RX DMA termination on TX prepare failure Carlos Song (OSS)
2026-05-20 10:30 ` sashiko-bot
@ 2026-05-20 16:57 ` Frank Li
1 sibling, 0 replies; 7+ messages in thread
From: Frank Li @ 2026-05-20 16:57 UTC (permalink / raw)
To: Carlos Song (OSS)
Cc: broonie, xiaoning.wang, Fugang.duan, linux-spi, imx, linux-kernel,
Carlos Song, stable
On Wed, May 20, 2026 at 05:43:08PM +0800, Carlos Song (OSS) wrote:
> From: Carlos Song <carlos.song@nxp.com>
>
> When dmaengine_prep_slave_sg() fails for the TX channel, the error path
> only terminates the TX DMA channel but leaves the RX channel running.
> Since the RX channel was already submitted and issued prior to preparing
> the TX descriptor, returning -EINVAL causes the SPI core to unmap the
> DMA buffers while the RX DMA engine continues writing to them, leading
> to potential memory corruption or use-after-free.
>
> Fix this by also terminating the RX channel before returning on the TX
> prepare failure path.
>
> Fixes: 09c04466ce7e ("spi: lpspi: add dma mode support")
> Cc: stable@vger.kernel.org
> Signed-off-by: Carlos Song <carlos.song@nxp.com>
> ---
> change for v2:
> - Add fix missing RX DMA termination on TX prepare failure.
> ---
> drivers/spi/spi-fsl-lpspi.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
> index 1a94a42fac31..906892453a84 100644
> --- a/drivers/spi/spi-fsl-lpspi.c
> +++ b/drivers/spi/spi-fsl-lpspi.c
> @@ -647,6 +647,7 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller,
> tx->sgl, tx->nents, DMA_MEM_TO_DEV,
> DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
> if (!desc_tx) {
> + dmaengine_terminate_sync(controller->dma_rx);
> dmaengine_terminate_sync(controller->dma_tx);
Are you sure need terminate tx ? suppose tx have not submitted yet because
failure to prep.
I think it's should be typo previously, you intent temerate dma_rx insteand
dma_tx at beginning.
Frank
> return -EINVAL;
> }
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-05-20 16:57 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-20 9:43 [PATCH v2 0/2] spi: fsl-lpspi: fix DMA termination issues Carlos Song (OSS)
2026-05-20 9:43 ` [PATCH v2 1/2] spi: fsl-lpspi: replace dmaengine_terminate_all with dmaengine_terminate_sync Carlos Song (OSS)
2026-05-20 10:00 ` sashiko-bot
2026-05-20 16:52 ` Frank Li
2026-05-20 9:43 ` [PATCH v2 2/2] spi: fsl-lpspi: fix missing RX DMA termination on TX prepare failure Carlos Song (OSS)
2026-05-20 10:30 ` sashiko-bot
2026-05-20 16:57 ` Frank Li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox