When the Freescale i.MX SPI driver falls back from DMA to PIO mode due to a transfer error, it fails to undo the hardware state changes that DMA mode requires. The driver's bounce-buffer optimization — added for performance — bypasses the SPI core's xfer->{tx,rx}_sg_mapped flags, which normally trigger the core's built-in DMA-to-PIO recovery mechanism. Your code correctly handles the NULL return from dmaengine_prep_slave_single(), but the fallback path never clears CTRL.SMC or restores the non-DMA burst length. The SPI peripheral continues operating in a hybrid state: PIO logic feeding data into hardware still configured for DMA.

The fix — setting controller->fallback in the error path — works because it re-triggers can_dma(), which clears the DMA flag and forces setupxfer() to reconfigure the hardware correctly. But understand what you've inherited: a three-hop implicit contract that isn't documented anywhere in the code. Future maintainers modifying the DMA path will see spi_imx->usedma read but not written in the fallback case and may 'correct' it, breaking this recovery chain.

Audit your own SPI drivers for the same pattern. Any custom DMA-to-PIO fallback that bypasses xfer->{tx,rx}_sg_mapped carries this risk. The failure manifests as silent data corruption at the protocol layer — the driver believes the transfer succeeded — and only devices with their own integrity checks (like TPMs) will surface the problem. Systems with non-validating SPI devices may corrupt silently indefinitely.