]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
dmaengine: tegra: Fix burst size calculation
authorKartik Rajput <kkartik@nvidia.com>
Wed, 22 Apr 2026 06:41:34 +0000 (12:11 +0530)
committerVinod Koul <vkoul@kernel.org>
Mon, 8 Jun 2026 12:13:48 +0000 (17:43 +0530)
Currently, the Tegra GPC DMA hardware requires the transfer length to
be a multiple of the max burst size configured for the channel. When a
client requests a transfer where the length is not evenly divisible by
the configured max burst size, the DMA hangs with partial burst at
the end.

Fix this by reducing the burst size to the largest power-of-2 value
that evenly divides the transfer length. For example, a 40-byte
transfer with a 16-byte max burst will now use an 8-byte burst
(40 / 8 = 5 complete bursts) instead of causing a hang.

This issue was observed with the PL011 UART driver where TX DMA
transfers of arbitrary lengths were stuck.

Fixes: ee17028009d4 ("dmaengine: tegra: Add tegra gpcdma driver")
Cc: stable@vger.kernel.org
Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Link: https://patch.msgid.link/20260422064134.1323610-1-kkartik@nvidia.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/dma/tegra186-gpc-dma.c

index c364c278a8b0686363f48f97b9ad3d0d33a51421..64cedef1050ae54a27ca40c61cc0b81cc49f2d19 100644 (file)
@@ -835,6 +835,13 @@ static unsigned int get_burst_size(struct tegra_dma_channel *tdc,
         * len to calculate the optimum burst size
         */
        burst_byte = burst_size ? burst_size * slave_bw : len;
+
+       /*
+        * Find the largest burst size that evenly divides the transfer length.
+        * The hardware requires the transfer length to be a multiple of the
+        * burst size - partial bursts are not supported.
+        */
+       burst_byte = min(burst_byte, 1U << __ffs(len));
        burst_mmio_width = burst_byte / 4;
 
        if (burst_mmio_width < TEGRA_GPCDMA_MMIOSEQ_BURST_MIN)