1 From: Felix Fietkau <nbd@openwrt.org>
2 Date: Sun, 12 Apr 2015 22:23:07 +0200
3 Subject: [PATCH] bgmac: simplify rx DMA error handling
5 Unmap the DMA buffer before checking it. If an error occurs, free the
6 buffer and allocate a new one. If allocation or mapping fails, retry as
7 long as there is NAPI poll budget left (count every attempt instead of
10 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
13 --- a/drivers/net/ethernet/broadcom/bgmac.c
14 +++ b/drivers/net/ethernet/broadcom/bgmac.c
15 @@ -404,51 +404,33 @@ static int bgmac_dma_rx_read(struct bgma
16 void *buf = slot->buf;
19 - /* Unmap buffer to make it accessible to the CPU */
20 - dma_sync_single_for_cpu(dma_dev, slot->dma_addr,
21 - BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
23 - /* Get info from the header */
24 - len = le16_to_cpu(rx->len);
25 - flags = le16_to_cpu(rx->flags);
26 + if (++handled >= weight - 1) /* Should never be greater */
30 - dma_addr_t old_dma_addr = slot->dma_addr;
32 + if (!slot->dma_addr)
35 + /* Unmap buffer to make it accessible to the CPU */
36 + dma_unmap_single(dma_dev, slot->dma_addr,
37 + BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
40 + /* Get info from the header */
41 + len = le16_to_cpu(rx->len);
42 + flags = le16_to_cpu(rx->flags);
44 /* Check for poison and drop or pass the packet */
45 if (len == 0xdead && flags == 0xbeef) {
46 bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n",
48 - dma_sync_single_for_device(dma_dev,
52 + put_page(virt_to_head_page(buf));
59 - /* Prepare new skb as replacement */
60 - err = bgmac_dma_rx_skb_for_slot(bgmac, slot);
62 - /* Poison the old skb */
63 - rx->len = cpu_to_le16(0xdead);
64 - rx->flags = cpu_to_le16(0xbeef);
66 - dma_sync_single_for_device(dma_dev,
72 - bgmac_dma_rx_setup_desc(bgmac, ring, ring->start);
74 - /* Unmap old skb, we'll pass it to the netfif */
75 - dma_unmap_single(dma_dev, old_dma_addr,
76 - BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
78 skb = build_skb(buf, BGMAC_RX_ALLOC_SIZE);
79 skb_put(skb, BGMAC_RX_FRAME_OFFSET +
80 BGMAC_RX_BUF_OFFSET + len);
81 @@ -458,14 +440,16 @@ static int bgmac_dma_rx_read(struct bgma
82 skb_checksum_none_assert(skb);
83 skb->protocol = eth_type_trans(skb, bgmac->net_dev);
84 napi_gro_receive(&bgmac->napi, skb);
88 + /* Prepare new skb as replacement */
89 + if (bgmac_dma_rx_skb_for_slot(bgmac, slot))
92 + bgmac_dma_rx_setup_desc(bgmac, ring, ring->start);
94 if (++ring->start >= BGMAC_RX_RING_SLOTS)
97 - if (handled >= weight) /* Should never be greater */
102 @@ -528,14 +512,14 @@ static void bgmac_dma_rx_ring_free(struc
104 for (i = 0; i < ring->num_slots; i++) {
105 slot = &ring->slots[i];
107 + if (!slot->dma_addr)
110 - if (slot->dma_addr)
111 - dma_unmap_single(dma_dev, slot->dma_addr,
114 + dma_unmap_single(dma_dev, slot->dma_addr,
117 put_page(virt_to_head_page(slot->buf));
118 + slot->dma_addr = 0;