kernel: finally remove layer7 filter support
[openwrt.git] / target / linux / generic / patches-3.18 / 077-07-bgmac-simplify-rx-DMA-error-handling.patch
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
4
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
8 every frame).
9
10 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
11 ---
12
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;
17                 u16 len, flags;
18  
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);
22 -
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 */
27 +                       break;
28  
29                 do {
30 -                       dma_addr_t old_dma_addr = slot->dma_addr;
31 -                       int err;
32 +                       if (!slot->dma_addr)
33 +                               break;
34 +
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);
38 +                       slot->dma_addr = 0;
39 +
40 +                       /* Get info from the header */
41 +                       len = le16_to_cpu(rx->len);
42 +                       flags = le16_to_cpu(rx->flags);
43  
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",
47                                           ring->start);
48 -                               dma_sync_single_for_device(dma_dev,
49 -                                                          slot->dma_addr,
50 -                                                          BGMAC_RX_BUF_SIZE,
51 -                                                          DMA_FROM_DEVICE);
52 +                               put_page(virt_to_head_page(buf));
53                                 break;
54                         }
55  
56                         /* Omit CRC. */
57                         len -= ETH_FCS_LEN;
58  
59 -                       /* Prepare new skb as replacement */
60 -                       err = bgmac_dma_rx_skb_for_slot(bgmac, slot);
61 -                       if (err) {
62 -                               /* Poison the old skb */
63 -                               rx->len = cpu_to_le16(0xdead);
64 -                               rx->flags = cpu_to_le16(0xbeef);
65 -
66 -                               dma_sync_single_for_device(dma_dev,
67 -                                                          slot->dma_addr,
68 -                                                          BGMAC_RX_BUF_SIZE,
69 -                                                          DMA_FROM_DEVICE);
70 -                               break;
71 -                       }
72 -                       bgmac_dma_rx_setup_desc(bgmac, ring, ring->start);
73 -
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);
77 -
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);
85 -                       handled++;
86                 } while (0);
87  
88 +               /* Prepare new skb as replacement */
89 +               if (bgmac_dma_rx_skb_for_slot(bgmac, slot))
90 +                       continue;
91 +
92 +               bgmac_dma_rx_setup_desc(bgmac, ring, ring->start);
93 +
94                 if (++ring->start >= BGMAC_RX_RING_SLOTS)
95                         ring->start = 0;
96 -
97 -               if (handled >= weight) /* Should never be greater */
98 -                       break;
99         }
100  
101         return handled;
102 @@ -528,14 +512,14 @@ static void bgmac_dma_rx_ring_free(struc
103  
104         for (i = 0; i < ring->num_slots; i++) {
105                 slot = &ring->slots[i];
106 -               if (!slot->buf)
107 +               if (!slot->dma_addr)
108                         continue;
109  
110 -               if (slot->dma_addr)
111 -                       dma_unmap_single(dma_dev, slot->dma_addr,
112 -                                        BGMAC_RX_BUF_SIZE,
113 -                                        DMA_FROM_DEVICE);
114 +               dma_unmap_single(dma_dev, slot->dma_addr,
115 +                                BGMAC_RX_BUF_SIZE,
116 +                                DMA_FROM_DEVICE);
117                 put_page(virt_to_head_page(slot->buf));
118 +               slot->dma_addr = 0;
119         }
120  }
121