diff options
author | Rafał Miłecki <zajec5@gmail.com> | 2015-04-23 19:11:11 +0000 |
---|---|---|
committer | Rafał Miłecki <zajec5@gmail.com> | 2015-04-23 19:11:11 +0000 |
commit | e175b199f8b5947ee498d049b2f4dff694e08e72 (patch) | |
tree | 4b05b80ec4ce1411d37dba7006cc5a8534672108 /target/linux/generic/patches-4.0/072-11-bgmac-fix-DMA-rx-corruption.patch | |
parent | 62e7f07615192b909ddb71408e67c4938b08b3cc (diff) | |
download | upstream-e175b199f8b5947ee498d049b2f4dff694e08e72.tar.gz upstream-e175b199f8b5947ee498d049b2f4dff694e08e72.tar.bz2 upstream-e175b199f8b5947ee498d049b2f4dff694e08e72.zip |
kernel: backport rest of bgmac patches to 4.0
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
SVN-Revision: 45573
Diffstat (limited to 'target/linux/generic/patches-4.0/072-11-bgmac-fix-DMA-rx-corruption.patch')
-rw-r--r-- | target/linux/generic/patches-4.0/072-11-bgmac-fix-DMA-rx-corruption.patch | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/target/linux/generic/patches-4.0/072-11-bgmac-fix-DMA-rx-corruption.patch b/target/linux/generic/patches-4.0/072-11-bgmac-fix-DMA-rx-corruption.patch new file mode 100644 index 0000000000..2e670d89b0 --- /dev/null +++ b/target/linux/generic/patches-4.0/072-11-bgmac-fix-DMA-rx-corruption.patch @@ -0,0 +1,88 @@ +From: Felix Fietkau <nbd@openwrt.org> +Date: Sun, 12 Apr 2015 11:59:47 +0200 +Subject: [PATCH] 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: Felix Fietkau <nbd@openwrt.org> +--- + +--- a/drivers/net/ethernet/broadcom/bgmac.c ++++ b/drivers/net/ethernet/broadcom/bgmac.c +@@ -366,6 +366,16 @@ static int bgmac_dma_rx_skb_for_slot(str + return 0; + } + ++static void bgmac_dma_rx_update_index(struct bgmac *bgmac, ++ struct bgmac_dma_ring *ring) ++{ ++ 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, + struct bgmac_dma_ring *ring, int desc_idx) + { +@@ -384,6 +394,8 @@ static void bgmac_dma_rx_setup_desc(stru + 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->ctl1 = cpu_to_le32(ctl1); ++ ++ ring->end = desc_idx; + } + + static void bgmac_dma_rx_poison_buf(struct device *dma_dev, +@@ -411,9 +423,7 @@ static int bgmac_dma_rx_read(struct bgma + end_slot &= BGMAC_DMA_RX_STATDPTR; + end_slot /= sizeof(struct bgmac_dma_desc); + +- ring->end = end_slot; +- +- while (ring->start != ring->end) { ++ while (ring->start != end_slot) { + struct device *dma_dev = bgmac->core->dma_dev; + struct bgmac_slot_info *slot = &ring->slots[ring->start]; + struct bgmac_rx_header *rx = slot->buf + BGMAC_RX_BUF_OFFSET; +@@ -476,6 +486,8 @@ static int bgmac_dma_rx_read(struct bgma + break; + } + ++ bgmac_dma_rx_update_index(bgmac, ring); ++ + return handled; + } + +@@ -695,6 +707,8 @@ static int bgmac_dma_init(struct bgmac * + if (ring->unaligned) + bgmac_dma_rx_enable(bgmac, ring); + ++ ring->start = 0; ++ ring->end = 0; + for (j = 0; j < ring->num_slots; j++) { + err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]); + if (err) +@@ -703,12 +717,7 @@ static int bgmac_dma_init(struct bgmac * + bgmac_dma_rx_setup_desc(bgmac, ring, j); + } + +- bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX, +- ring->index_base + +- ring->num_slots * sizeof(struct bgmac_dma_desc)); +- +- ring->start = 0; +- ring->end = 0; ++ bgmac_dma_rx_update_index(bgmac, ring); + } + + return 0; |