RE: [PATCH] spi: imx: reconfigure for PIO when DMA cannot be started
From: Carlos Song (OSS)
Date: Wed Jun 24 2026 - 05:22:28 EST
> -----Original Message-----
> From: Javier Fernandez Pastrana <javier.pastrana@xxxxxxxxxxxxx>
> Sent: Tuesday, June 23, 2026 11:33 PM
> To: Mark Brown <broonie@xxxxxxxxxx>; Frank Li <frank.li@xxxxxxx>; Sascha
> Hauer <s.hauer@xxxxxxxxxxxxxx>; Pengutronix Kernel Team
> <kernel@xxxxxxxxxxxxxx>; Fabio Estevam <festevam@xxxxxxxxx>; Carlos Song
> <carlos.song@xxxxxxx>; linux-spi@xxxxxxxxxxxxxxx; imx@xxxxxxxxxxxxxxx;
> linux-arm-kernel@xxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx
> Cc: javier.pastrana@xxxxxxxxxxxxx; stable@xxxxxxxxxxxxxxx
> Subject: [PATCH] spi: imx: reconfigure for PIO when DMA cannot be started
>
> [You don't often get email from javier.pastrana@xxxxxxxxxxxxx. Learn why this is
> important at https://aka.ms/LearnAboutSenderIdentification ]
>
> When spi_imx_can_dma() selects DMA, the ECSPI is configured for DMA:
> spi_imx_setupxfer() sets CTRL.SMC and clears dynamic_burst, and
> spi_imx_dma_transfer() programs the dynamic-burst BURST_LENGTH and the
> SDMA watermarks.
>
> If the DMA descriptor cannot be prepared (dmaengine_prep_slave_single()
> returns NULL), the transfer is failed with SPI_TRANS_FAIL_NO_START and falls
> back to PIO. The dynamic-burst DMA path uses its own bounce buffers instead of
> the SPI core's mapping, so xfer->{tx,rx}_sg_mapped are not set and the core's
> DMA->PIO retry is skipped; the driver falls back to PIO internally. But none of the
> DMA-mode configuration is undone, so the PIO transfer runs with CTRL.SMC set,
> the wrong burst length and dynamic_burst cleared, and the transferred data is
> corrupted.
>
> This is easily hit on i.MX8MP boards that describe ECSPI DMA in the device tree
> but run SDMA on ROM firmware (no external sdma-imx7d.bin):
> every ECSPI DMA prepare fails. An Infineon SLB9670 TPM on ECSPI1 then returns
> shifted TPM2_GetCapability data, is flagged "field failure mode", /dev/tpmrm0 is
> never created.
>
> Mark the controller PIO-only (controller->fallback) and re-run
> spi_imx_setupxfer() before falling back, so the ECSPI is reconfigured exactly like a
> normal PIO transfer.
>
> Fixes: faa8e404ad8e ("spi: imx: support dynamic burst length for ECSPI DMA
> mode")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Javier Fernandez Pastrana <javier.pastrana@xxxxxxxxxxxxx>
> ---
> drivers/spi/spi-imx.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index
> 480d1e8b281f..64c78bd79d7d 100644
> --- a/drivers/spi/spi-imx.c
> +++ b/drivers/spi/spi-imx.c
> @@ -2153,6 +2153,8 @@ static int spi_imx_transfer_one(struct spi_controller
> *controller,
> ret = spi_imx_dma_transfer(spi_imx, transfer);
> if (transfer->error & SPI_TRANS_FAIL_NO_START) {
> spi_imx->usedma = false;
> + controller->fallback = true;
> + spi_imx_setupxfer(spi, transfer);
Hi, Javier
Thank you very much for fixing this issue!
You can remove this line also: spi_imx->usedma = false;
Because spi_imx_setupxfer() will recheck spi_imx_can_dma() and return false because controller->fallback = true;
How do you think about it?
Carlos Song
> if (spi_imx->target_mode)
> return spi_imx_pio_transfer_target(spi,
> transfer);
> else
> --
> 2.47.3
>