Commit 4668ae1f authored by Felix Fietkau's avatar Felix Fietkau Committed by David S. Miller

bgmac: fix DMA rx corruption

The driver needs to inform the hardware about the first invalid (not yet
filled) rx slot, by writing its DMA descriptor pointer offset to the
BGMAC_DMA_RX_INDEX register.

This register was set to a value exceeding the rx ring size, effectively
allowing the hardware constant access to the full ring, regardless of
which slots are initialized.

To fix this issue, always mark the last filled rx slot as invalid.
Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 74b6f291
...@@ -366,6 +366,16 @@ static int bgmac_dma_rx_skb_for_slot(struct bgmac *bgmac, ...@@ -366,6 +366,16 @@ static int bgmac_dma_rx_skb_for_slot(struct bgmac *bgmac,
return 0; return 0;
} }
static void bgmac_dma_rx_update_index(struct bgmac *bgmac,
struct bgmac_dma_ring *ring)
{
dma_wmb();
bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX,
ring->index_base +
ring->end * sizeof(struct bgmac_dma_desc));
}
static void bgmac_dma_rx_setup_desc(struct bgmac *bgmac, static void bgmac_dma_rx_setup_desc(struct bgmac *bgmac,
struct bgmac_dma_ring *ring, int desc_idx) struct bgmac_dma_ring *ring, int desc_idx)
{ {
...@@ -384,6 +394,8 @@ static void bgmac_dma_rx_setup_desc(struct bgmac *bgmac, ...@@ -384,6 +394,8 @@ static void bgmac_dma_rx_setup_desc(struct bgmac *bgmac,
dma_desc->addr_high = cpu_to_le32(upper_32_bits(ring->slots[desc_idx].dma_addr)); dma_desc->addr_high = cpu_to_le32(upper_32_bits(ring->slots[desc_idx].dma_addr));
dma_desc->ctl0 = cpu_to_le32(ctl0); dma_desc->ctl0 = cpu_to_le32(ctl0);
dma_desc->ctl1 = cpu_to_le32(ctl1); dma_desc->ctl1 = cpu_to_le32(ctl1);
ring->end = desc_idx;
} }
static void bgmac_dma_rx_poison_buf(struct device *dma_dev, static void bgmac_dma_rx_poison_buf(struct device *dma_dev,
...@@ -411,9 +423,7 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring, ...@@ -411,9 +423,7 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring,
end_slot &= BGMAC_DMA_RX_STATDPTR; end_slot &= BGMAC_DMA_RX_STATDPTR;
end_slot /= sizeof(struct bgmac_dma_desc); end_slot /= sizeof(struct bgmac_dma_desc);
ring->end = end_slot; while (ring->start != end_slot) {
while (ring->start != ring->end) {
struct device *dma_dev = bgmac->core->dma_dev; struct device *dma_dev = bgmac->core->dma_dev;
struct bgmac_slot_info *slot = &ring->slots[ring->start]; struct bgmac_slot_info *slot = &ring->slots[ring->start];
struct bgmac_rx_header *rx = slot->buf + BGMAC_RX_BUF_OFFSET; struct bgmac_rx_header *rx = slot->buf + BGMAC_RX_BUF_OFFSET;
...@@ -476,6 +486,8 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring, ...@@ -476,6 +486,8 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring,
break; break;
} }
bgmac_dma_rx_update_index(bgmac, ring);
return handled; return handled;
} }
...@@ -695,6 +707,8 @@ static int bgmac_dma_init(struct bgmac *bgmac) ...@@ -695,6 +707,8 @@ static int bgmac_dma_init(struct bgmac *bgmac)
if (ring->unaligned) if (ring->unaligned)
bgmac_dma_rx_enable(bgmac, ring); bgmac_dma_rx_enable(bgmac, ring);
ring->start = 0;
ring->end = 0;
for (j = 0; j < ring->num_slots; j++) { for (j = 0; j < ring->num_slots; j++) {
err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]); err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]);
if (err) if (err)
...@@ -703,12 +717,7 @@ static int bgmac_dma_init(struct bgmac *bgmac) ...@@ -703,12 +717,7 @@ static int bgmac_dma_init(struct bgmac *bgmac)
bgmac_dma_rx_setup_desc(bgmac, ring, j); bgmac_dma_rx_setup_desc(bgmac, ring, j);
} }
bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX, bgmac_dma_rx_update_index(bgmac, ring);
ring->index_base +
ring->num_slots * sizeof(struct bgmac_dma_desc));
ring->start = 0;
ring->end = 0;
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment