openwrt/target/linux/bcm27xx/patches-6.6/950-1372-dmaengine-dw-axi-dmac-Allow-client-chosen-width.patch
Álvaro Fernández Rojas 3a5584e0df bcm27xx: pull 6.6 patches from RPi repo
Adds latest 6.6 patches from the Raspberry Pi repository.

These patches were generated from:
https://github.com/raspberrypi/linux/commits/rpi-6.6.y/
With the following command:
git format-patch -N v6.6.67..HEAD
(HEAD -> 811ff707533bcd67cdcd368bbd46223082009b12)

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
(cherry picked from commit 692205305db14deeff1a2dc4a6d7f87e19fc418b)
2024-12-28 14:11:52 +01:00

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 |