Re: [PATCH v3 1/6] spi: spi-fsl-dspi: Clear completion counter before initiating transfer

From: James Clark
Date: Wed Jun 25 2025 - 05:55:25 EST




On 24/06/2025 4:58 pm, Frank Li wrote:
On Tue, Jun 24, 2025 at 11:35:31AM +0100, James Clark wrote:
In target mode, extra interrupts can be received between the end of a
transfer and halting the module if the host continues sending more data.
If the interrupt from this occurs after the reinit_completion() then the
completion counter is left at a non-zero value. The next unrelated
transfer initiated by userspace will then complete immediately without
waiting for the interrupt or writing to the RX buffer.

Fix it by resetting the counter before the transfer so that lingering
values are cleared. This is done after clearing the FIFOs and the
status register but before the transfer is initiated, so no interrupts
should be received at this point resulting in other race conditions.

Fixes: 4f5ee75ea171 ("spi: spi-fsl-dspi: Replace interruptible wait queue with a simple completion")
Signed-off-by: James Clark <james.clark@xxxxxxxxxx>
---
drivers/spi/spi-fsl-dspi.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 04c88d090c4d..744dfc561db2 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -1122,11 +1122,19 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) {
status = dspi_dma_xfer(dspi);
} else {
+ /*
+ * Reset completion counter to clear any extra
+ * complete()s from spurious interrupts that may have
+ * happened after the last message's completion but
+ * before the module was fully in stop mode.
+ */

I think you change is correct. reinit_completion() should be called before
dspi_fifo_write().

comments is quite confused. how about below comments?

/*
* Reinitialize the completion before transferring data to avoid the case where
* it might remain in the done state due to a spurious interrupt from a previous
* transfer. This could falsely signal that the current transfer has completed.
*/

Frank

Will do

+ if (dspi->irq)
+ reinit_completion(&dspi->xfer_done);
+
dspi_fifo_write(dspi);

if (dspi->irq) {
wait_for_completion(&dspi->xfer_done);
- reinit_completion(&dspi->xfer_done);
} else {
do {
status = dspi_poll(dspi);

--
2.34.1