mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 15:12:13 +02:00
dmaengine: sun6i: Choose appropriate burst length under maxburst
maxburst, as provided by the client, specifies the largest amount of data that is allowed to be transferred in one burst. This limit is normally provided to avoid a data burst overflowing the target FIFO. It does not mean that the DMA engine can only do bursts in that size. Let the driver pick the largest supported burst length within the given limit. This lets the driver work correctly with some clients that give a large maxburst value. In particular, the 8250_dw driver will give a quarter of the UART's FIFO size as maxburst. On some systems the FIFO size is 256 bytes, giving a maxburst of 64 bytes, while the hardware only supports bursts of up to 16 bytes. Signed-off-by: Chen-Yu Tsai <wens@kernel.org> Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com> Link: https://patch.msgid.link/20251221080450.1813479-1-wens@kernel.org Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
parent
98b9f207af
commit
7178c3586a
|
|
@ -583,6 +583,22 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static u32 find_burst_size(const u32 burst_lengths, u32 maxburst)
|
||||
{
|
||||
if (!maxburst)
|
||||
return 1;
|
||||
|
||||
if (BIT(maxburst) & burst_lengths)
|
||||
return maxburst;
|
||||
|
||||
/* Hardware only does power-of-two bursts. */
|
||||
for (u32 burst = rounddown_pow_of_two(maxburst); burst > 0; burst /= 2)
|
||||
if (BIT(burst) & burst_lengths)
|
||||
return burst;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int set_config(struct sun6i_dma_dev *sdev,
|
||||
struct dma_slave_config *sconfig,
|
||||
enum dma_transfer_direction direction,
|
||||
|
|
@ -616,15 +632,13 @@ static int set_config(struct sun6i_dma_dev *sdev,
|
|||
return -EINVAL;
|
||||
if (!(BIT(dst_addr_width) & sdev->slave.dst_addr_widths))
|
||||
return -EINVAL;
|
||||
if (!(BIT(src_maxburst) & sdev->cfg->src_burst_lengths))
|
||||
return -EINVAL;
|
||||
if (!(BIT(dst_maxburst) & sdev->cfg->dst_burst_lengths))
|
||||
return -EINVAL;
|
||||
|
||||
src_width = convert_buswidth(src_addr_width);
|
||||
dst_width = convert_buswidth(dst_addr_width);
|
||||
dst_burst = convert_burst(dst_maxburst);
|
||||
src_burst = convert_burst(src_maxburst);
|
||||
src_burst = find_burst_size(sdev->cfg->src_burst_lengths, src_maxburst);
|
||||
dst_burst = find_burst_size(sdev->cfg->dst_burst_lengths, dst_maxburst);
|
||||
dst_burst = convert_burst(dst_burst);
|
||||
src_burst = convert_burst(src_burst);
|
||||
|
||||
*p_cfg = DMA_CHAN_CFG_SRC_WIDTH(src_width) |
|
||||
DMA_CHAN_CFG_DST_WIDTH(dst_width);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user