>From de229c0b2602a2cf3d936993a7946f3cb7a80ef2 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 27 Jun 2025 23:57:53 +0300 Subject: [PATCH 2/3] spi: fsl-dspi: fix logic bug introduced by previous commit dspi_rxtx() is actually "rx, and then tx if necessary". Refactoring the code to look at dspi->len outside of this function means we are losing a necessary call to dspi_fifo_read(). This makes XSPI-based transfers eventually hang. I don't necessarily agree with the premise that using an errno value privately within the driver is an anti-pattern, but let's at least make the code functionally correct and use a boolean to track whether there is data left to send, while still allowing data to be received. Signed-off-by: Vladimir Oltean --- drivers/spi/spi-fsl-dspi.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index c0a6c6c6459e..e74ff6e9cb02 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -986,15 +986,20 @@ static void dspi_fifo_write(struct fsl_dspi *dspi) dspi->progress, !dspi->irq); } -static void dspi_rxtx(struct fsl_dspi *dspi) +/* Returns false if the buffer to be transmitted is empty, and true if + * there is still data to transmit. + */ +static bool dspi_rxtx(struct fsl_dspi *dspi) { dspi_fifo_read(dspi); if (!dspi->len) /* Success! */ - return; + return false; dspi_fifo_write(dspi); + + return true; } static int dspi_poll(struct fsl_dspi *dspi) @@ -1003,7 +1008,7 @@ static int dspi_poll(struct fsl_dspi *dspi) int err = 0; u32 spi_sr; - while (dspi->len) { + do { for (tries = 1000; tries > 0; --tries) { regmap_read(dspi->regmap, SPI_SR, &spi_sr); regmap_write(dspi->regmap, SPI_SR, spi_sr); @@ -1014,8 +1019,7 @@ static int dspi_poll(struct fsl_dspi *dspi) err = -ETIMEDOUT; break; } - dspi_rxtx(dspi); - } + } while (dspi_rxtx(dspi)); return err; } @@ -1031,9 +1035,7 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) if (!(spi_sr & SPI_SR_CMDTCF)) return IRQ_NONE; - dspi_rxtx(dspi); - - if (!dspi->len) + if (dspi_rxtx(dspi) == false) complete(&dspi->xfer_done); return IRQ_HANDLED; -- 2.34.1