1 From 793023dc148830c18c437b58d88a118a72091038 Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Thu, 13 Apr 2023 16:47:10 +0200
4 Subject: [PATCH] dmaengine: bcm2835: Fix descriptors usage for 40-bits
7 The bcm2835_dma_create_cb_chain() function is in charge of building up
8 the descriptors chain for a given transfer.
10 It was initially supporting only the BCM2835-style DMA controller, and
11 was later expanded to support controllers with 40-bits channels that use
12 a different descriptor layout.
14 However, some part of the function only use the old style descriptor,
15 even when building a chain of new-style descriptors, resulting in weird
18 Fixes: 9a52a9918306 ("bcm2835-dma: Add proper 40-bit DMA support")
19 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
21 drivers/dma/bcm2835-dma.c | 69 ++++++++++++++++++++++++++++-----------
22 1 file changed, 50 insertions(+), 19 deletions(-)
24 --- a/drivers/dma/bcm2835-dma.c
25 +++ b/drivers/dma/bcm2835-dma.c
26 @@ -543,7 +543,10 @@ static struct bcm2835_desc *bcm2835_dma_
27 cyclic ? finalextrainfo : 0);
29 /* calculate new remaining length */
30 - len -= control_block->length;
31 + if (c->is_40bit_channel)
32 + len -= ((struct bcm2711_dma40_scb *)control_block)->len;
34 + len -= control_block->length;
37 /* link this the last controlblock */
38 @@ -555,10 +558,19 @@ static struct bcm2835_desc *bcm2835_dma_
39 d->cb_list[frame - 1].cb->next = cb_entry->paddr;
41 /* update src and dst and length */
42 - if (src && (info & BCM2835_DMA_S_INC))
43 - src += control_block->length;
44 - if (dst && (info & BCM2835_DMA_D_INC))
45 - dst += control_block->length;
46 + if (src && (info & BCM2835_DMA_S_INC)) {
47 + if (c->is_40bit_channel)
48 + src += ((struct bcm2711_dma40_scb *)control_block)->len;
50 + src += control_block->length;
53 + if (dst && (info & BCM2835_DMA_D_INC)) {
54 + if (c->is_40bit_channel)
55 + dst += ((struct bcm2711_dma40_scb *)control_block)->len;
57 + dst += control_block->length;
60 /* Length of total transfer */
61 if (c->is_40bit_channel)
62 @@ -779,20 +791,39 @@ static size_t bcm2835_dma_desc_size_pos(
66 - for (size = i = 0; i < d->frames; i++) {
67 - struct bcm2835_dma_cb *control_block = d->cb_list[i].cb;
68 - size_t this_size = control_block->length;
71 - if (d->dir == DMA_DEV_TO_MEM)
72 - dma = control_block->dst;
74 - dma = control_block->src;
78 - else if (addr >= dma && addr < dma + this_size)
79 - size += dma + this_size - addr;
80 + if (d->c->is_40bit_channel) {
81 + for (size = i = 0; i < d->frames; i++) {
82 + struct bcm2711_dma40_scb *control_block =
83 + (struct bcm2711_dma40_scb *)d->cb_list[i].cb;
84 + size_t this_size = control_block->len;
87 + if (d->dir == DMA_DEV_TO_MEM)
88 + dma = control_block->dst;
90 + dma = control_block->src;
94 + else if (addr >= dma && addr < dma + this_size)
95 + size += dma + this_size - addr;
98 + for (size = i = 0; i < d->frames; i++) {
99 + struct bcm2835_dma_cb *control_block = d->cb_list[i].cb;
100 + size_t this_size = control_block->length;
103 + if (d->dir == DMA_DEV_TO_MEM)
104 + dma = control_block->dst;
106 + dma = control_block->src;
110 + else if (addr >= dma && addr < dma + this_size)
111 + size += dma + this_size - addr;