[PATCH RESEND] dmaengine: tegra: Fix burst size calculation

Kartik Rajput posted 1 patch 1 month, 2 weeks ago
drivers/dma/tegra186-gpc-dma.c | 7 +++++++
1 file changed, 7 insertions(+)
[PATCH RESEND] dmaengine: tegra: Fix burst size calculation
Posted by Kartik Rajput 1 month, 2 weeks ago
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>
---
 drivers/dma/tegra186-gpc-dma.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index 5948fbf32c21..0aa3a02b2277 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -825,6 +825,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)
-- 
2.43.0
Re: [PATCH RESEND] dmaengine: tegra: Fix burst size calculation
Posted by Vinod Koul 2 days, 22 hours ago
On Wed, 22 Apr 2026 12:11:34 +0530, Kartik Rajput wrote:
> 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.
> 
> [...]

Applied, thanks!

[1/1] dmaengine: tegra: Fix burst size calculation
      commit: 4651df83b6c796daead3447e8fd874322918ee4f

Best regards,
-- 
~Vinod
Re: [PATCH RESEND] dmaengine: tegra: Fix burst size calculation
Posted by Jon Hunter 1 month, 2 weeks ago
On 22/04/2026 07:41, Kartik Rajput wrote:
> 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>
> ---
>   drivers/dma/tegra186-gpc-dma.c | 7 +++++++
>   1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
> index 5948fbf32c21..0aa3a02b2277 100644
> --- a/drivers/dma/tegra186-gpc-dma.c
> +++ b/drivers/dma/tegra186-gpc-dma.c
> @@ -825,6 +825,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)


Reviewed-by: Jon Hunter <jonathanh@nvidia.com>

Thanks
Jon

-- 
nvpublic
Re: [PATCH RESEND] dmaengine: tegra: Fix burst size calculation
Posted by Kartik Rajput 3 days, 4 hours ago
Hi Vinod,

On 22/04/26 14:56, Jon Hunter wrote:
> 
> On 22/04/2026 07:41, Kartik Rajput wrote:
>> 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>
>> ---
>>   drivers/dma/tegra186-gpc-dma.c | 7 +++++++
>>   1 file changed, 7 insertions(+)
>>
>> diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
>> index 5948fbf32c21..0aa3a02b2277 100644
>> --- a/drivers/dma/tegra186-gpc-dma.c
>> +++ b/drivers/dma/tegra186-gpc-dma.c
>> @@ -825,6 +825,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)
> 
> 
> Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
> 
> Thanks
> Jon
> 

This applies cleanly on top of Akhil's Tegra264 series:
https://lore.kernel.org/linux-tegra/20260331102303.33181-1-akhilrajeev@nvidia.com/T/#t

Could you please pick this up if there are no objections?

Thanks,
Kartik