]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
spi: spi-fsl-dspi: Use whole page for DMA buffers
authorJames Clark <james.clark@linaro.org>
Tue, 2 Sep 2025 12:44:57 +0000 (13:44 +0100)
committerMark Brown <broonie@kernel.org>
Wed, 3 Sep 2025 13:30:32 +0000 (14:30 +0100)
dma_alloc_noncoherent() allocations are backed by a full page anyway, so
use it all.

VF610 devices used to use the full page before commit a957499bd437
("spi: spi-fsl-dspi: Fix bits-per-word acceleration in DMA mode"), but
others still used the FIFO size. After that commit, all devices used the
FIFO size. Now all devices use the full page.

Signed-off-by: James Clark <james.clark@linaro.org>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Message-ID: <20250902-james-nxp-spi-dma-v6-5-f7aa2c5e56e2@linaro.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-fsl-dspi.c

index 81d1e4470f948e87eef8b99501a75d37db882434..6bf87ef01c13d1385d33a1ad13130194e7bffca4 100644 (file)
@@ -331,6 +331,8 @@ struct fsl_dspi_dma {
        dma_addr_t                              rx_dma_phys;
        struct completion                       cmd_rx_complete;
        struct dma_async_tx_descriptor          *rx_desc;
+
+       size_t                                  bufsize;
 };
 
 struct fsl_dspi {
@@ -493,6 +495,24 @@ static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi)
        return cmd << 16 | data;
 }
 
+static size_t dspi_dma_max_datawords(struct fsl_dspi *dspi)
+{
+       /*
+        * Transfers look like one of these, so we always use a full DMA word
+        * regardless of SPI word size:
+        *
+        * 31              16 15                   0
+        * -----------------------------------------
+        * |   CONTROL WORD  |     16-bit DATA     |
+        * -----------------------------------------
+        * or
+        * -----------------------------------------
+        * |   CONTROL WORD  | UNUSED | 8-bit DATA |
+        * -----------------------------------------
+        */
+       return dspi->dma->bufsize / DMA_SLAVE_BUSWIDTH_4_BYTES;
+}
+
 static size_t dspi_dma_transfer_size(struct fsl_dspi *dspi)
 {
        return dspi->words_in_flight * DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -620,9 +640,8 @@ static void dspi_dma_xfer(struct fsl_dspi *dspi)
                /* Figure out operational bits-per-word for this chunk */
                dspi_setup_accel(dspi);
 
-               dspi->words_in_flight = dspi->len / dspi->oper_word_size;
-               if (dspi->words_in_flight > dspi->devtype_data->fifo_size)
-                       dspi->words_in_flight = dspi->devtype_data->fifo_size;
+               dspi->words_in_flight = min(dspi->len / dspi->oper_word_size,
+                                           dspi_dma_max_datawords(dspi));
 
                message->actual_length += dspi->words_in_flight *
                                          dspi->oper_word_size;
@@ -637,7 +656,6 @@ static void dspi_dma_xfer(struct fsl_dspi *dspi)
 
 static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
 {
-       int dma_bufsize = dspi->devtype_data->fifo_size * 2;
        struct device *dev = &dspi->pdev->dev;
        struct dma_slave_config cfg;
        struct fsl_dspi_dma *dma;
@@ -657,8 +675,10 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
                goto err_tx_channel;
        }
 
+       dma->bufsize = PAGE_SIZE;
+
        dma->tx_dma_buf = dma_alloc_noncoherent(dma->chan_tx->device->dev,
-                                               dma_bufsize, &dma->tx_dma_phys,
+                                               dma->bufsize, &dma->tx_dma_phys,
                                                DMA_TO_DEVICE, GFP_KERNEL);
        if (!dma->tx_dma_buf) {
                ret = -ENOMEM;
@@ -666,7 +686,7 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
        }
 
        dma->rx_dma_buf = dma_alloc_noncoherent(dma->chan_rx->device->dev,
-                                               dma_bufsize, &dma->rx_dma_phys,
+                                               dma->bufsize, &dma->rx_dma_phys,
                                                DMA_FROM_DEVICE, GFP_KERNEL);
        if (!dma->rx_dma_buf) {
                ret = -ENOMEM;
@@ -702,11 +722,11 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
        return 0;
 
 err_slave_config:
-       dma_free_noncoherent(dma->chan_rx->device->dev, dma_bufsize,
+       dma_free_noncoherent(dma->chan_rx->device->dev, dma->bufsize,
                             dma->rx_dma_buf, dma->rx_dma_phys,
                             DMA_FROM_DEVICE);
 err_rx_dma_buf:
-       dma_free_noncoherent(dma->chan_tx->device->dev, dma_bufsize,
+       dma_free_noncoherent(dma->chan_tx->device->dev, dma->bufsize,
                             dma->tx_dma_buf, dma->tx_dma_phys, DMA_TO_DEVICE);
 err_tx_dma_buf:
        dma_release_channel(dma->chan_tx);
@@ -721,21 +741,20 @@ err_tx_channel:
 
 static void dspi_release_dma(struct fsl_dspi *dspi)
 {
-       int dma_bufsize = dspi->devtype_data->fifo_size * 2;
        struct fsl_dspi_dma *dma = dspi->dma;
 
        if (!dma)
                return;
 
        if (dma->chan_tx) {
-               dma_free_noncoherent(dma->chan_tx->device->dev, dma_bufsize,
+               dma_free_noncoherent(dma->chan_tx->device->dev, dma->bufsize,
                                     dma->tx_dma_buf, dma->tx_dma_phys,
                                     DMA_TO_DEVICE);
                dma_release_channel(dma->chan_tx);
        }
 
        if (dma->chan_rx) {
-               dma_free_noncoherent(dma->chan_rx->device->dev, dma_bufsize,
+               dma_free_noncoherent(dma->chan_rx->device->dev, dma->bufsize,
                                     dma->rx_dma_buf, dma->rx_dma_phys,
                                     DMA_FROM_DEVICE);
                dma_release_channel(dma->chan_rx);