Unverified Commit fbb618e1 authored by James Clark's avatar James Clark Committed by Mark Brown
Browse files

spi: spi-fsl-dspi: Use whole page for DMA buffers



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 a957499b
("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: default avatarJames Clark <james.clark@linaro.org>
Reviewed-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Message-ID: <20250902-james-nxp-spi-dma-v6-5-f7aa2c5e56e2@linaro.org>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 36db0b03
Loading
Loading
Loading
Loading
+30 −11
Original line number Diff line number Diff line
@@ -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 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)

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);