xburst: Remove unmaintained target
[openwrt/staging/mkresin.git] / target / linux / generic / pending-3.18 / 077-11-bgmac-fix-DMA-rx-corruption.patch
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Sun, 12 Apr 2015 11:59:47 +0200
3 Subject: [PATCH] bgmac: fix DMA rx corruption
4
5 The driver needs to inform the hardware about the first invalid (not yet
6 filled) rx slot, by writing its DMA descriptor pointer offset to the
7 BGMAC_DMA_RX_INDEX register.
8
9 This register was set to a value exceeding the rx ring size, effectively
10 allowing the hardware constant access to the full ring, regardless of
11 which slots are initialized.
12
13 To fix this issue, always mark the last filled rx slot as invalid.
14
15 Signed-off-by: Felix Fietkau <nbd@nbd.name>
16 ---
17
18 --- a/drivers/net/ethernet/broadcom/bgmac.c
19 +++ b/drivers/net/ethernet/broadcom/bgmac.c
20 @@ -366,6 +366,16 @@ static int bgmac_dma_rx_skb_for_slot(str
21 return 0;
22 }
23
24 +static void bgmac_dma_rx_update_index(struct bgmac *bgmac,
25 + struct bgmac_dma_ring *ring)
26 +{
27 + wmb();
28 +
29 + bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX,
30 + ring->index_base +
31 + ring->end * sizeof(struct bgmac_dma_desc));
32 +}
33 +
34 static void bgmac_dma_rx_setup_desc(struct bgmac *bgmac,
35 struct bgmac_dma_ring *ring, int desc_idx)
36 {
37 @@ -384,6 +394,8 @@ static void bgmac_dma_rx_setup_desc(stru
38 dma_desc->addr_high = cpu_to_le32(upper_32_bits(ring->slots[desc_idx].dma_addr));
39 dma_desc->ctl0 = cpu_to_le32(ctl0);
40 dma_desc->ctl1 = cpu_to_le32(ctl1);
41 +
42 + ring->end = desc_idx;
43 }
44
45 static void bgmac_dma_rx_poison_buf(struct device *dma_dev,
46 @@ -411,9 +423,7 @@ static int bgmac_dma_rx_read(struct bgma
47 end_slot &= BGMAC_DMA_RX_STATDPTR;
48 end_slot /= sizeof(struct bgmac_dma_desc);
49
50 - ring->end = end_slot;
51 -
52 - while (ring->start != ring->end) {
53 + while (ring->start != end_slot) {
54 struct device *dma_dev = bgmac->core->dma_dev;
55 struct bgmac_slot_info *slot = &ring->slots[ring->start];
56 struct bgmac_rx_header *rx = slot->buf + BGMAC_RX_BUF_OFFSET;
57 @@ -476,6 +486,8 @@ static int bgmac_dma_rx_read(struct bgma
58 break;
59 }
60
61 + bgmac_dma_rx_update_index(bgmac, ring);
62 +
63 return handled;
64 }
65
66 @@ -695,6 +707,8 @@ static int bgmac_dma_init(struct bgmac *
67 if (ring->unaligned)
68 bgmac_dma_rx_enable(bgmac, ring);
69
70 + ring->start = 0;
71 + ring->end = 0;
72 for (j = 0; j < ring->num_slots; j++) {
73 err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]);
74 if (err)
75 @@ -703,12 +717,7 @@ static int bgmac_dma_init(struct bgmac *
76 bgmac_dma_rx_setup_desc(bgmac, ring, j);
77 }
78
79 - bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX,
80 - ring->index_base +
81 - ring->num_slots * sizeof(struct bgmac_dma_desc));
82 -
83 - ring->start = 0;
84 - ring->end = 0;
85 + bgmac_dma_rx_update_index(bgmac, ring);
86 }
87
88 return 0;