summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2015-04-14 06:08:01 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-14 14:57:11 -0400
commit4668ae1fbcab89af5ffbb161d4c70b25ce4c50f4 (patch)
tree10bdada0183fa33d78be95ab81b4d7cba5839710 /drivers/net
parent74b6f29163490d88ff53f7c54d0e4514bbf1630b (diff)
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> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/broadcom/bgmac.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 79216d6cc0c9..29af9e656a7a 100644
--- 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(struct bgmac *bgmac,
366 return 0; 366 return 0;
367} 367}
368 368
369static void bgmac_dma_rx_update_index(struct bgmac *bgmac,
370 struct bgmac_dma_ring *ring)
371{
372 dma_wmb();
373
374 bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX,
375 ring->index_base +
376 ring->end * sizeof(struct bgmac_dma_desc));
377}
378
369static void bgmac_dma_rx_setup_desc(struct bgmac *bgmac, 379static void bgmac_dma_rx_setup_desc(struct bgmac *bgmac,
370 struct bgmac_dma_ring *ring, int desc_idx) 380 struct bgmac_dma_ring *ring, int desc_idx)
371{ 381{
@@ -384,6 +394,8 @@ static void bgmac_dma_rx_setup_desc(struct bgmac *bgmac,
384 dma_desc->addr_high = cpu_to_le32(upper_32_bits(ring->slots[desc_idx].dma_addr)); 394 dma_desc->addr_high = cpu_to_le32(upper_32_bits(ring->slots[desc_idx].dma_addr));
385 dma_desc->ctl0 = cpu_to_le32(ctl0); 395 dma_desc->ctl0 = cpu_to_le32(ctl0);
386 dma_desc->ctl1 = cpu_to_le32(ctl1); 396 dma_desc->ctl1 = cpu_to_le32(ctl1);
397
398 ring->end = desc_idx;
387} 399}
388 400
389static void bgmac_dma_rx_poison_buf(struct device *dma_dev, 401static 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 end_slot &= BGMAC_DMA_RX_STATDPTR; 423 end_slot &= BGMAC_DMA_RX_STATDPTR;
412 end_slot /= sizeof(struct bgmac_dma_desc); 424 end_slot /= sizeof(struct bgmac_dma_desc);
413 425
414 ring->end = end_slot; 426 while (ring->start != end_slot) {
415
416 while (ring->start != ring->end) {
417 struct device *dma_dev = bgmac->core->dma_dev; 427 struct device *dma_dev = bgmac->core->dma_dev;
418 struct bgmac_slot_info *slot = &ring->slots[ring->start]; 428 struct bgmac_slot_info *slot = &ring->slots[ring->start];
419 struct bgmac_rx_header *rx = slot->buf + BGMAC_RX_BUF_OFFSET; 429 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 break; 486 break;
477 } 487 }
478 488
489 bgmac_dma_rx_update_index(bgmac, ring);
490
479 return handled; 491 return handled;
480} 492}
481 493
@@ -695,6 +707,8 @@ static int bgmac_dma_init(struct bgmac *bgmac)
695 if (ring->unaligned) 707 if (ring->unaligned)
696 bgmac_dma_rx_enable(bgmac, ring); 708 bgmac_dma_rx_enable(bgmac, ring);
697 709
710 ring->start = 0;
711 ring->end = 0;
698 for (j = 0; j < ring->num_slots; j++) { 712 for (j = 0; j < ring->num_slots; j++) {
699 err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]); 713 err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]);
700 if (err) 714 if (err)
@@ -703,12 +717,7 @@ static int bgmac_dma_init(struct bgmac *bgmac)
703 bgmac_dma_rx_setup_desc(bgmac, ring, j); 717 bgmac_dma_rx_setup_desc(bgmac, ring, j);
704 } 718 }
705 719
706 bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX, 720 bgmac_dma_rx_update_index(bgmac, ring);
707 ring->index_base +
708 ring->num_slots * sizeof(struct bgmac_dma_desc));
709
710 ring->start = 0;
711 ring->end = 0;
712 } 721 }
713 722
714 return 0; 723 return 0;