kernel: update kernel 3.18 to version 3.18.23
[openwrt/staging/chunkeey.git] / target / linux / generic / patches-3.18 / 077-02-bgmac-implement-GRO-and-use-build_skb.patch
1 From: Felix Fietkau <nbd@openwrt.org>
2 Date: Mon, 23 Mar 2015 02:41:25 +0100
3 Subject: [PATCH] bgmac: implement GRO and use build_skb
4
5 This improves performance for routing and local rx
6
7 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
8 ---
9
10 --- a/drivers/net/ethernet/broadcom/bgmac.c
11 +++ b/drivers/net/ethernet/broadcom/bgmac.c
12 @@ -276,31 +276,31 @@ static int bgmac_dma_rx_skb_for_slot(str
13 struct bgmac_slot_info *slot)
14 {
15 struct device *dma_dev = bgmac->core->dma_dev;
16 - struct sk_buff *skb;
17 dma_addr_t dma_addr;
18 struct bgmac_rx_header *rx;
19 + void *buf;
20
21 /* Alloc skb */
22 - skb = netdev_alloc_skb(bgmac->net_dev, BGMAC_RX_BUF_SIZE);
23 - if (!skb)
24 + buf = netdev_alloc_frag(BGMAC_RX_ALLOC_SIZE);
25 + if (!buf)
26 return -ENOMEM;
27
28 /* Poison - if everything goes fine, hardware will overwrite it */
29 - rx = (struct bgmac_rx_header *)skb->data;
30 + rx = buf;
31 rx->len = cpu_to_le16(0xdead);
32 rx->flags = cpu_to_le16(0xbeef);
33
34 /* Map skb for the DMA */
35 - dma_addr = dma_map_single(dma_dev, skb->data,
36 - BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
37 + dma_addr = dma_map_single(dma_dev, buf, BGMAC_RX_BUF_SIZE,
38 + DMA_FROM_DEVICE);
39 if (dma_mapping_error(dma_dev, dma_addr)) {
40 bgmac_err(bgmac, "DMA mapping error\n");
41 - dev_kfree_skb(skb);
42 + put_page(virt_to_head_page(buf));
43 return -ENOMEM;
44 }
45
46 /* Update the slot */
47 - slot->skb = skb;
48 + slot->buf = buf;
49 slot->dma_addr = dma_addr;
50
51 return 0;
52 @@ -343,8 +343,9 @@ static int bgmac_dma_rx_read(struct bgma
53 while (ring->start != ring->end) {
54 struct device *dma_dev = bgmac->core->dma_dev;
55 struct bgmac_slot_info *slot = &ring->slots[ring->start];
56 - struct sk_buff *skb = slot->skb;
57 - struct bgmac_rx_header *rx;
58 + struct bgmac_rx_header *rx = slot->buf;
59 + struct sk_buff *skb;
60 + void *buf = slot->buf;
61 u16 len, flags;
62
63 /* Unmap buffer to make it accessible to the CPU */
64 @@ -352,7 +353,6 @@ static int bgmac_dma_rx_read(struct bgma
65 BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
66
67 /* Get info from the header */
68 - rx = (struct bgmac_rx_header *)skb->data;
69 len = le16_to_cpu(rx->len);
70 flags = le16_to_cpu(rx->flags);
71
72 @@ -393,12 +393,13 @@ static int bgmac_dma_rx_read(struct bgma
73 dma_unmap_single(dma_dev, old_dma_addr,
74 BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
75
76 + skb = build_skb(buf, BGMAC_RX_ALLOC_SIZE);
77 skb_put(skb, BGMAC_RX_FRAME_OFFSET + len);
78 skb_pull(skb, BGMAC_RX_FRAME_OFFSET);
79
80 skb_checksum_none_assert(skb);
81 skb->protocol = eth_type_trans(skb, bgmac->net_dev);
82 - netif_receive_skb(skb);
83 + napi_gro_receive(&bgmac->napi, skb);
84 handled++;
85 } while (0);
86
87 @@ -434,12 +435,11 @@ static bool bgmac_dma_unaligned(struct b
88 return false;
89 }
90
91 -static void bgmac_dma_ring_free(struct bgmac *bgmac,
92 - struct bgmac_dma_ring *ring)
93 +static void bgmac_dma_tx_ring_free(struct bgmac *bgmac,
94 + struct bgmac_dma_ring *ring)
95 {
96 struct device *dma_dev = bgmac->core->dma_dev;
97 struct bgmac_slot_info *slot;
98 - int size;
99 int i;
100
101 for (i = 0; i < ring->num_slots; i++) {
102 @@ -451,23 +451,55 @@ static void bgmac_dma_ring_free(struct b
103 dev_kfree_skb(slot->skb);
104 }
105 }
106 +}
107 +
108 +static void bgmac_dma_rx_ring_free(struct bgmac *bgmac,
109 + struct bgmac_dma_ring *ring)
110 +{
111 + struct device *dma_dev = bgmac->core->dma_dev;
112 + struct bgmac_slot_info *slot;
113 + int i;
114 +
115 + for (i = 0; i < ring->num_slots; i++) {
116 + slot = &ring->slots[i];
117 + if (!slot->buf)
118 + continue;
119
120 - if (ring->cpu_base) {
121 - /* Free ring of descriptors */
122 - size = ring->num_slots * sizeof(struct bgmac_dma_desc);
123 - dma_free_coherent(dma_dev, size, ring->cpu_base,
124 - ring->dma_base);
125 + if (slot->dma_addr)
126 + dma_unmap_single(dma_dev, slot->dma_addr,
127 + BGMAC_RX_BUF_SIZE,
128 + DMA_FROM_DEVICE);
129 + put_page(virt_to_head_page(slot->buf));
130 }
131 }
132
133 +static void bgmac_dma_ring_desc_free(struct bgmac *bgmac,
134 + struct bgmac_dma_ring *ring)
135 +{
136 + struct device *dma_dev = bgmac->core->dma_dev;
137 + int size;
138 +
139 + if (!ring->cpu_base)
140 + return;
141 +
142 + /* Free ring of descriptors */
143 + size = ring->num_slots * sizeof(struct bgmac_dma_desc);
144 + dma_free_coherent(dma_dev, size, ring->cpu_base,
145 + ring->dma_base);
146 +}
147 +
148 static void bgmac_dma_free(struct bgmac *bgmac)
149 {
150 int i;
151
152 - for (i = 0; i < BGMAC_MAX_TX_RINGS; i++)
153 - bgmac_dma_ring_free(bgmac, &bgmac->tx_ring[i]);
154 - for (i = 0; i < BGMAC_MAX_RX_RINGS; i++)
155 - bgmac_dma_ring_free(bgmac, &bgmac->rx_ring[i]);
156 + for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) {
157 + bgmac_dma_tx_ring_free(bgmac, &bgmac->tx_ring[i]);
158 + bgmac_dma_ring_desc_free(bgmac, &bgmac->tx_ring[i]);
159 + }
160 + for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) {
161 + bgmac_dma_rx_ring_free(bgmac, &bgmac->rx_ring[i]);
162 + bgmac_dma_ring_desc_free(bgmac, &bgmac->rx_ring[i]);
163 + }
164 }
165
166 static int bgmac_dma_alloc(struct bgmac *bgmac)
167 --- a/drivers/net/ethernet/broadcom/bgmac.h
168 +++ b/drivers/net/ethernet/broadcom/bgmac.h
169 @@ -362,6 +362,8 @@
170 #define BGMAC_RX_FRAME_OFFSET 30 /* There are 2 unused bytes between header and real data */
171 #define BGMAC_RX_MAX_FRAME_SIZE 1536 /* Copied from b44/tg3 */
172 #define BGMAC_RX_BUF_SIZE (BGMAC_RX_FRAME_OFFSET + BGMAC_RX_MAX_FRAME_SIZE)
173 +#define BGMAC_RX_ALLOC_SIZE (SKB_DATA_ALIGN(BGMAC_RX_BUF_SIZE) + \
174 + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
175
176 #define BGMAC_BFL_ENETROBO 0x0010 /* has ephy roboswitch spi */
177 #define BGMAC_BFL_ENETADM 0x0080 /* has ADMtek switch */
178 @@ -383,7 +385,10 @@
179 #define ETHER_MAX_LEN 1518
180
181 struct bgmac_slot_info {
182 - struct sk_buff *skb;
183 + union {
184 + struct sk_buff *skb;
185 + void *buf;
186 + };
187 dma_addr_t dma_addr;
188 };
189