]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
spi: imx: Fix precedence bug in spi_imx_dma_max_wml_find()
authorJohn Madieu <john.madieu@gmail.com>
Fri, 1 May 2026 13:59:49 +0000 (13:59 +0000)
committerMark Brown <broonie@kernel.org>
Mon, 4 May 2026 13:22:14 +0000 (22:22 +0900)
The watermark search in spi_imx_dma_max_wml_find() reads:

if (!dma_data->dma_len % (i * bytes_per_word))
break;

The unary ! binds tighter than %, so this parses as:

if ((!dma_data->dma_len) % (i * bytes_per_word))
break;

!dma_data->dma_len is 0 or 1, and `0 % x == 0` for any x; `1 % x` is
0 unless x == 1. The condition is therefore false in every case
except dma_len != 0 with i * bytes_per_word == 1, i.e. i == 1 and
bytes_per_word == 1.

The loop almost always falls through to its end, leaving i == 0,
which the post-loop fallback rewrites to 1:

if (i == 0)
i = 1;

So spi_imx->wml ends up at 1 for essentially every DMA transfer,
defeating the entire purpose of the function. The DMA engine then
requests service after every single FIFO word instead of using
multi-word bursts, hurting throughput on every DMA-capable variant.

Add the missing parentheses so the modulo is computed first, then
negated:

if (!(dma_data->dma_len % (i * bytes_per_word)))
break;

Fixes: faa8e404ad8e ("spi: imx: support dynamic burst length for ECSPI DMA mode")
Signed-off-by: John Madieu <john.madieu@gmail.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260501135951.2416527-2-john.madieu@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-imx.c

index e5c907c45b8786c12f774a090ab8a58055b2d33e..7ae8078c10efa0b7153b24ee2ced7ba9bc1ff4a1 100644 (file)
@@ -1836,7 +1836,7 @@ static void spi_imx_dma_max_wml_find(struct spi_imx_data *spi_imx,
        unsigned int i;
 
        for (i = spi_imx->devtype_data->fifo_size / 2; i > 0; i--) {
-               if (!dma_data->dma_len % (i * bytes_per_word))
+               if (!(dma_data->dma_len % (i * bytes_per_word)))
                        break;
        }
        /* Use 1 as wml in case no available burst length got */