Skip to content

Commit fa60c09

Browse files
james-c-linarobroonie
authored andcommitted
spi: spi-fsl-dspi: Clear completion counter before initiating transfer
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: 4f5ee75 ("spi: spi-fsl-dspi: Replace interruptible wait queue with a simple completion") Signed-off-by: James Clark <[email protected]> Reviewed-by: Frank Li <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 96893cd commit fa60c09

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

drivers/spi/spi-fsl-dspi.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,11 +983,20 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
983983
if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) {
984984
status = dspi_dma_xfer(dspi);
985985
} else {
986+
/*
987+
* Reinitialize the completion before transferring data
988+
* to avoid the case where it might remain in the done
989+
* state due to a spurious interrupt from a previous
990+
* transfer. This could falsely signal that the current
991+
* transfer has completed.
992+
*/
993+
if (dspi->irq)
994+
reinit_completion(&dspi->xfer_done);
995+
986996
dspi_fifo_write(dspi);
987997

988998
if (dspi->irq) {
989999
wait_for_completion(&dspi->xfer_done);
990-
reinit_completion(&dspi->xfer_done);
9911000
} else {
9921001
do {
9931002
status = dspi_poll(dspi);

0 commit comments

Comments
 (0)