mirror of
https://github.com/openwrt/openwrt.git
synced 2025-01-27 06:39:51 +00:00
41 lines
1.8 KiB
Diff
41 lines
1.8 KiB
Diff
|
From a2fa911d90495762047c05dec4241308ae61ca36 Mon Sep 17 00:00:00 2001
|
||
|
From: Phil Elwell <phil@raspberrypi.com>
|
||
|
Date: Thu, 19 Sep 2024 18:05:00 +0100
|
||
|
Subject: [PATCH] dmaengine: dw-axi-dmac: Allow client-chosen width
|
||
|
|
||
|
For devices where transfer lengths are not known upfront, there is a
|
||
|
danger when the destination is wider than the source that partial words
|
||
|
can be lost at the end of a transfer. Ideally the controller would be
|
||
|
able to flush the residue, but it can't - it's not even possible to tell
|
||
|
that there is any.
|
||
|
|
||
|
Instead, allow the client driver to avoid the problem by setting a
|
||
|
smaller width.
|
||
|
|
||
|
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||
|
---
|
||
|
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 12 ++++++++++++
|
||
|
1 file changed, 12 insertions(+)
|
||
|
|
||
|
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
|
||
|
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
|
||
|
@@ -724,6 +724,18 @@ static int dw_axi_dma_set_hw_desc(struct
|
||
|
case DMA_DEV_TO_MEM:
|
||
|
reg_burst_msize = axi_dma_encode_msize(chan->config.src_maxburst);
|
||
|
reg_width = __ffs(chan->config.src_addr_width);
|
||
|
+ /*
|
||
|
+ * For devices where transfer lengths are not known upfront,
|
||
|
+ * there is a danger when the destination is wider than the
|
||
|
+ * source that partial words can be lost at the end of a transfer.
|
||
|
+ * Ideally the controller would be able to flush the residue, but
|
||
|
+ * it can't - it's not even possible to tell that there is any.
|
||
|
+ * Instead, allow the client driver to avoid the problem by setting
|
||
|
+ * a smaller width.
|
||
|
+ */
|
||
|
+ if (chan->config.dst_addr_width &&
|
||
|
+ (chan->config.dst_addr_width < mem_width))
|
||
|
+ mem_width = chan->config.dst_addr_width;
|
||
|
device_addr = phys_to_dma(chan->chip->dev, chan->config.src_addr);
|
||
|
ctllo = reg_width << CH_CTL_L_SRC_WIDTH_POS |
|
||
|
mem_width << CH_CTL_L_DST_WIDTH_POS |
|