From: James Clark Date: Tue, 2 Sep 2025 12:44:58 +0000 (+0100) Subject: spi: spi-fsl-dspi: Increase target mode DMA buffer size X-Git-Tag: v6.18-rc1~165^2~14^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7d9baf1e530930e28b45805e3855a4a465a9e36e;p=thirdparty%2Fkernel%2Flinux.git spi: spi-fsl-dspi: Increase target mode DMA buffer size When the device is configured as a target, the host won't stop sending data while we're draining the buffer which leads to FIFO underflows and corruption. Increase the DMA buffer size to the maximum words that edma can transfer once to reduce the chance of this happening. In host mode, the driver is able to split up a transfer into smaller chunks so we don't need to increase the size. While in target mode, the length of the transfer is determined by the remote host and can be larger than whatever default buffer size we pick. Keeping the buffer small in host mode avoids wasting memory, but allocating the largest possible in target mode gives the lowest possible chance of dropping any data from the host. While we could allocate per-transfer using the exact size of the transfer, 128K is quite a large allocation and there is a chance it could fail due to memory fragmentation unless it's allocated once at init time. Signed-off-by: Larisa Grigore Signed-off-by: James Clark Reviewed-by: Vladimir Oltean Message-ID: <20250902-james-nxp-spi-dma-v6-6-f7aa2c5e56e2@linaro.org> Signed-off-by: Mark Brown --- diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 6bf87ef01c13d..3d29285c772c4 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -675,7 +675,18 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr) goto err_tx_channel; } - dma->bufsize = PAGE_SIZE; + if (spi_controller_is_target(dspi->ctlr)) { + /* + * In target mode we have to be ready to receive the maximum + * that can possibly be transferred at once by EDMA without any + * FIFO underflows. + */ + dma->bufsize = min(dma_get_max_seg_size(dma->chan_rx->device->dev), + dma_get_max_seg_size(dma->chan_tx->device->dev)) * + DMA_SLAVE_BUSWIDTH_4_BYTES; + } else { + dma->bufsize = PAGE_SIZE; + } dma->tx_dma_buf = dma_alloc_noncoherent(dma->chan_tx->device->dev, dma->bufsize, &dma->tx_dma_phys,