image.mk: fix emitting profiles for targets that have no subtargets
[openwrt/staging/mkresin.git] / package / kernel / mac80211 / patches / 349-0006-brcmfmac-cleanup-ampdu-rx-host-reorder-code.patch
1 From: Arend van Spriel <arend@broadcom.com>
2 Date: Mon, 11 Apr 2016 11:35:26 +0200
3 Subject: [PATCH] brcmfmac: cleanup ampdu-rx host reorder code
4
5 The code for ampdu-rx host reorder is related to the firmware signalling
6 supported in BCDC protocol. This change moves the code to fwsignal module.
7
8 Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
9 Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
10 Reviewed-by: Franky Lin <franky.lin@broadcom.com>
11 Signed-off-by: Arend van Spriel <arend@broadcom.com>
12 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
13 ---
14
15 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
16 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
17 @@ -351,6 +351,12 @@ brcmf_proto_bcdc_add_tdls_peer(struct br
18 {
19 }
20
21 +static void brcmf_proto_bcdc_rxreorder(struct brcmf_if *ifp,
22 + struct sk_buff *skb)
23 +{
24 + brcmf_fws_rxreorder(ifp, skb);
25 +}
26 +
27 int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
28 {
29 struct brcmf_bcdc *bcdc;
30 @@ -372,6 +378,7 @@ int brcmf_proto_bcdc_attach(struct brcmf
31 drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode;
32 drvr->proto->delete_peer = brcmf_proto_bcdc_delete_peer;
33 drvr->proto->add_tdls_peer = brcmf_proto_bcdc_add_tdls_peer;
34 + drvr->proto->rxreorder = brcmf_proto_bcdc_rxreorder;
35 drvr->proto->pd = bcdc;
36
37 drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
38 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
39 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
40 @@ -40,19 +40,6 @@
41
42 #define MAX_WAIT_FOR_8021X_TX msecs_to_jiffies(950)
43
44 -/* AMPDU rx reordering definitions */
45 -#define BRCMF_RXREORDER_FLOWID_OFFSET 0
46 -#define BRCMF_RXREORDER_MAXIDX_OFFSET 2
47 -#define BRCMF_RXREORDER_FLAGS_OFFSET 4
48 -#define BRCMF_RXREORDER_CURIDX_OFFSET 6
49 -#define BRCMF_RXREORDER_EXPIDX_OFFSET 8
50 -
51 -#define BRCMF_RXREORDER_DEL_FLOW 0x01
52 -#define BRCMF_RXREORDER_FLUSH_ALL 0x02
53 -#define BRCMF_RXREORDER_CURIDX_VALID 0x04
54 -#define BRCMF_RXREORDER_EXPIDX_VALID 0x08
55 -#define BRCMF_RXREORDER_NEW_HOLE 0x10
56 -
57 #define BRCMF_BSSIDX_INVALID -1
58
59 char *brcmf_ifname(struct brcmf_if *ifp)
60 @@ -342,207 +329,11 @@ void brcmf_netif_rx(struct brcmf_if *ifp
61 netif_rx_ni(skb);
62 }
63
64 -static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi,
65 - u8 start, u8 end,
66 - struct sk_buff_head *skb_list)
67 -{
68 - /* initialize return list */
69 - __skb_queue_head_init(skb_list);
70 -
71 - if (rfi->pend_pkts == 0) {
72 - brcmf_dbg(INFO, "no packets in reorder queue\n");
73 - return;
74 - }
75 -
76 - do {
77 - if (rfi->pktslots[start]) {
78 - __skb_queue_tail(skb_list, rfi->pktslots[start]);
79 - rfi->pktslots[start] = NULL;
80 - }
81 - start++;
82 - if (start > rfi->max_idx)
83 - start = 0;
84 - } while (start != end);
85 - rfi->pend_pkts -= skb_queue_len(skb_list);
86 -}
87 -
88 -static void brcmf_rxreorder_process_info(struct brcmf_if *ifp, u8 *reorder_data,
89 - struct sk_buff *pkt)
90 -{
91 - u8 flow_id, max_idx, cur_idx, exp_idx, end_idx;
92 - struct brcmf_ampdu_rx_reorder *rfi;
93 - struct sk_buff_head reorder_list;
94 - struct sk_buff *pnext;
95 - u8 flags;
96 - u32 buf_size;
97 -
98 - flow_id = reorder_data[BRCMF_RXREORDER_FLOWID_OFFSET];
99 - flags = reorder_data[BRCMF_RXREORDER_FLAGS_OFFSET];
100 -
101 - /* validate flags and flow id */
102 - if (flags == 0xFF) {
103 - brcmf_err("invalid flags...so ignore this packet\n");
104 - brcmf_netif_rx(ifp, pkt, false);
105 - return;
106 - }
107 -
108 - rfi = ifp->drvr->reorder_flows[flow_id];
109 - if (flags & BRCMF_RXREORDER_DEL_FLOW) {
110 - brcmf_dbg(INFO, "flow-%d: delete\n",
111 - flow_id);
112 -
113 - if (rfi == NULL) {
114 - brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
115 - flow_id);
116 - brcmf_netif_rx(ifp, pkt, false);
117 - return;
118 - }
119 -
120 - brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, rfi->exp_idx,
121 - &reorder_list);
122 - /* add the last packet */
123 - __skb_queue_tail(&reorder_list, pkt);
124 - kfree(rfi);
125 - ifp->drvr->reorder_flows[flow_id] = NULL;
126 - goto netif_rx;
127 - }
128 - /* from here on we need a flow reorder instance */
129 - if (rfi == NULL) {
130 - buf_size = sizeof(*rfi);
131 - max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
132 -
133 - buf_size += (max_idx + 1) * sizeof(pkt);
134 -
135 - /* allocate space for flow reorder info */
136 - brcmf_dbg(INFO, "flow-%d: start, maxidx %d\n",
137 - flow_id, max_idx);
138 - rfi = kzalloc(buf_size, GFP_ATOMIC);
139 - if (rfi == NULL) {
140 - brcmf_err("failed to alloc buffer\n");
141 - brcmf_netif_rx(ifp, pkt, false);
142 - return;
143 - }
144 -
145 - ifp->drvr->reorder_flows[flow_id] = rfi;
146 - rfi->pktslots = (struct sk_buff **)(rfi+1);
147 - rfi->max_idx = max_idx;
148 - }
149 - if (flags & BRCMF_RXREORDER_NEW_HOLE) {
150 - if (rfi->pend_pkts) {
151 - brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx,
152 - rfi->exp_idx,
153 - &reorder_list);
154 - WARN_ON(rfi->pend_pkts);
155 - } else {
156 - __skb_queue_head_init(&reorder_list);
157 - }
158 - rfi->cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
159 - rfi->exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
160 - rfi->max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
161 - rfi->pktslots[rfi->cur_idx] = pkt;
162 - rfi->pend_pkts++;
163 - brcmf_dbg(DATA, "flow-%d: new hole %d (%d), pending %d\n",
164 - flow_id, rfi->cur_idx, rfi->exp_idx, rfi->pend_pkts);
165 - } else if (flags & BRCMF_RXREORDER_CURIDX_VALID) {
166 - cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
167 - exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
168 -
169 - if ((exp_idx == rfi->exp_idx) && (cur_idx != rfi->exp_idx)) {
170 - /* still in the current hole */
171 - /* enqueue the current on the buffer chain */
172 - if (rfi->pktslots[cur_idx] != NULL) {
173 - brcmf_dbg(INFO, "HOLE: ERROR buffer pending..free it\n");
174 - brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
175 - rfi->pktslots[cur_idx] = NULL;
176 - }
177 - rfi->pktslots[cur_idx] = pkt;
178 - rfi->pend_pkts++;
179 - rfi->cur_idx = cur_idx;
180 - brcmf_dbg(DATA, "flow-%d: store pkt %d (%d), pending %d\n",
181 - flow_id, cur_idx, exp_idx, rfi->pend_pkts);
182 -
183 - /* can return now as there is no reorder
184 - * list to process.
185 - */
186 - return;
187 - }
188 - if (rfi->exp_idx == cur_idx) {
189 - if (rfi->pktslots[cur_idx] != NULL) {
190 - brcmf_dbg(INFO, "error buffer pending..free it\n");
191 - brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
192 - rfi->pktslots[cur_idx] = NULL;
193 - }
194 - rfi->pktslots[cur_idx] = pkt;
195 - rfi->pend_pkts++;
196 -
197 - /* got the expected one. flush from current to expected
198 - * and update expected
199 - */
200 - brcmf_dbg(DATA, "flow-%d: expected %d (%d), pending %d\n",
201 - flow_id, cur_idx, exp_idx, rfi->pend_pkts);
202 -
203 - rfi->cur_idx = cur_idx;
204 - rfi->exp_idx = exp_idx;
205 -
206 - brcmf_rxreorder_get_skb_list(rfi, cur_idx, exp_idx,
207 - &reorder_list);
208 - brcmf_dbg(DATA, "flow-%d: freeing buffers %d, pending %d\n",
209 - flow_id, skb_queue_len(&reorder_list),
210 - rfi->pend_pkts);
211 - } else {
212 - u8 end_idx;
213 -
214 - brcmf_dbg(DATA, "flow-%d (0x%x): both moved, old %d/%d, new %d/%d\n",
215 - flow_id, flags, rfi->cur_idx, rfi->exp_idx,
216 - cur_idx, exp_idx);
217 - if (flags & BRCMF_RXREORDER_FLUSH_ALL)
218 - end_idx = rfi->exp_idx;
219 - else
220 - end_idx = exp_idx;
221 -
222 - /* flush pkts first */
223 - brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
224 - &reorder_list);
225 -
226 - if (exp_idx == ((cur_idx + 1) % (rfi->max_idx + 1))) {
227 - __skb_queue_tail(&reorder_list, pkt);
228 - } else {
229 - rfi->pktslots[cur_idx] = pkt;
230 - rfi->pend_pkts++;
231 - }
232 - rfi->exp_idx = exp_idx;
233 - rfi->cur_idx = cur_idx;
234 - }
235 - } else {
236 - /* explicity window move updating the expected index */
237 - exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
238 -
239 - brcmf_dbg(DATA, "flow-%d (0x%x): change expected: %d -> %d\n",
240 - flow_id, flags, rfi->exp_idx, exp_idx);
241 - if (flags & BRCMF_RXREORDER_FLUSH_ALL)
242 - end_idx = rfi->exp_idx;
243 - else
244 - end_idx = exp_idx;
245 -
246 - brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
247 - &reorder_list);
248 - __skb_queue_tail(&reorder_list, pkt);
249 - /* set the new expected idx */
250 - rfi->exp_idx = exp_idx;
251 - }
252 -netif_rx:
253 - skb_queue_walk_safe(&reorder_list, pkt, pnext) {
254 - __skb_unlink(pkt, &reorder_list);
255 - brcmf_netif_rx(ifp, pkt, false);
256 - }
257 -}
258 -
259 void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_evnt)
260 {
261 struct brcmf_if *ifp;
262 struct brcmf_bus *bus_if = dev_get_drvdata(dev);
263 struct brcmf_pub *drvr = bus_if->drvr;
264 - struct brcmf_skb_reorder_data *rd;
265 int ret;
266
267 brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
268 @@ -557,9 +348,8 @@ void brcmf_rx_frame(struct device *dev,
269 return;
270 }
271
272 - rd = (struct brcmf_skb_reorder_data *)skb->cb;
273 - if (rd->reorder)
274 - brcmf_rxreorder_process_info(ifp, rd->reorder, skb);
275 + if (brcmf_proto_is_reorder_skb(skb))
276 + brcmf_proto_rxreorder(ifp, skb);
277 else
278 brcmf_netif_rx(ifp, skb, handle_evnt);
279 }
280 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
281 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
282 @@ -208,10 +208,6 @@ struct brcmf_if {
283 u8 ipv6addr_idx;
284 };
285
286 -struct brcmf_skb_reorder_data {
287 - u8 *reorder;
288 -};
289 -
290 int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
291
292 /* Return pointer to interface name */
293 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
294 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
295 @@ -92,6 +92,19 @@ enum brcmf_fws_tlv_len {
296 };
297 #undef BRCMF_FWS_TLV_DEF
298
299 +/* AMPDU rx reordering definitions */
300 +#define BRCMF_RXREORDER_FLOWID_OFFSET 0
301 +#define BRCMF_RXREORDER_MAXIDX_OFFSET 2
302 +#define BRCMF_RXREORDER_FLAGS_OFFSET 4
303 +#define BRCMF_RXREORDER_CURIDX_OFFSET 6
304 +#define BRCMF_RXREORDER_EXPIDX_OFFSET 8
305 +
306 +#define BRCMF_RXREORDER_DEL_FLOW 0x01
307 +#define BRCMF_RXREORDER_FLUSH_ALL 0x02
308 +#define BRCMF_RXREORDER_CURIDX_VALID 0x04
309 +#define BRCMF_RXREORDER_EXPIDX_VALID 0x08
310 +#define BRCMF_RXREORDER_NEW_HOLE 0x10
311 +
312 #ifdef DEBUG
313 /*
314 * brcmf_fws_tlv_names - array of tlv names.
315 @@ -1614,6 +1627,202 @@ static int brcmf_fws_notify_bcmc_credit_
316 return 0;
317 }
318
319 +static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi,
320 + u8 start, u8 end,
321 + struct sk_buff_head *skb_list)
322 +{
323 + /* initialize return list */
324 + __skb_queue_head_init(skb_list);
325 +
326 + if (rfi->pend_pkts == 0) {
327 + brcmf_dbg(INFO, "no packets in reorder queue\n");
328 + return;
329 + }
330 +
331 + do {
332 + if (rfi->pktslots[start]) {
333 + __skb_queue_tail(skb_list, rfi->pktslots[start]);
334 + rfi->pktslots[start] = NULL;
335 + }
336 + start++;
337 + if (start > rfi->max_idx)
338 + start = 0;
339 + } while (start != end);
340 + rfi->pend_pkts -= skb_queue_len(skb_list);
341 +}
342 +
343 +void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt)
344 +{
345 + u8 *reorder_data;
346 + u8 flow_id, max_idx, cur_idx, exp_idx, end_idx;
347 + struct brcmf_ampdu_rx_reorder *rfi;
348 + struct sk_buff_head reorder_list;
349 + struct sk_buff *pnext;
350 + u8 flags;
351 + u32 buf_size;
352 +
353 + reorder_data = ((struct brcmf_skb_reorder_data *)pkt->cb)->reorder;
354 + flow_id = reorder_data[BRCMF_RXREORDER_FLOWID_OFFSET];
355 + flags = reorder_data[BRCMF_RXREORDER_FLAGS_OFFSET];
356 +
357 + /* validate flags and flow id */
358 + if (flags == 0xFF) {
359 + brcmf_err("invalid flags...so ignore this packet\n");
360 + brcmf_netif_rx(ifp, pkt, false);
361 + return;
362 + }
363 +
364 + rfi = ifp->drvr->reorder_flows[flow_id];
365 + if (flags & BRCMF_RXREORDER_DEL_FLOW) {
366 + brcmf_dbg(INFO, "flow-%d: delete\n",
367 + flow_id);
368 +
369 + if (rfi == NULL) {
370 + brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
371 + flow_id);
372 + brcmf_netif_rx(ifp, pkt, false);
373 + return;
374 + }
375 +
376 + brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, rfi->exp_idx,
377 + &reorder_list);
378 + /* add the last packet */
379 + __skb_queue_tail(&reorder_list, pkt);
380 + kfree(rfi);
381 + ifp->drvr->reorder_flows[flow_id] = NULL;
382 + goto netif_rx;
383 + }
384 + /* from here on we need a flow reorder instance */
385 + if (rfi == NULL) {
386 + buf_size = sizeof(*rfi);
387 + max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
388 +
389 + buf_size += (max_idx + 1) * sizeof(pkt);
390 +
391 + /* allocate space for flow reorder info */
392 + brcmf_dbg(INFO, "flow-%d: start, maxidx %d\n",
393 + flow_id, max_idx);
394 + rfi = kzalloc(buf_size, GFP_ATOMIC);
395 + if (rfi == NULL) {
396 + brcmf_err("failed to alloc buffer\n");
397 + brcmf_netif_rx(ifp, pkt, false);
398 + return;
399 + }
400 +
401 + ifp->drvr->reorder_flows[flow_id] = rfi;
402 + rfi->pktslots = (struct sk_buff **)(rfi + 1);
403 + rfi->max_idx = max_idx;
404 + }
405 + if (flags & BRCMF_RXREORDER_NEW_HOLE) {
406 + if (rfi->pend_pkts) {
407 + brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx,
408 + rfi->exp_idx,
409 + &reorder_list);
410 + WARN_ON(rfi->pend_pkts);
411 + } else {
412 + __skb_queue_head_init(&reorder_list);
413 + }
414 + rfi->cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
415 + rfi->exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
416 + rfi->max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
417 + rfi->pktslots[rfi->cur_idx] = pkt;
418 + rfi->pend_pkts++;
419 + brcmf_dbg(DATA, "flow-%d: new hole %d (%d), pending %d\n",
420 + flow_id, rfi->cur_idx, rfi->exp_idx, rfi->pend_pkts);
421 + } else if (flags & BRCMF_RXREORDER_CURIDX_VALID) {
422 + cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
423 + exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
424 +
425 + if ((exp_idx == rfi->exp_idx) && (cur_idx != rfi->exp_idx)) {
426 + /* still in the current hole */
427 + /* enqueue the current on the buffer chain */
428 + if (rfi->pktslots[cur_idx] != NULL) {
429 + brcmf_dbg(INFO, "HOLE: ERROR buffer pending..free it\n");
430 + brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
431 + rfi->pktslots[cur_idx] = NULL;
432 + }
433 + rfi->pktslots[cur_idx] = pkt;
434 + rfi->pend_pkts++;
435 + rfi->cur_idx = cur_idx;
436 + brcmf_dbg(DATA, "flow-%d: store pkt %d (%d), pending %d\n",
437 + flow_id, cur_idx, exp_idx, rfi->pend_pkts);
438 +
439 + /* can return now as there is no reorder
440 + * list to process.
441 + */
442 + return;
443 + }
444 + if (rfi->exp_idx == cur_idx) {
445 + if (rfi->pktslots[cur_idx] != NULL) {
446 + brcmf_dbg(INFO, "error buffer pending..free it\n");
447 + brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
448 + rfi->pktslots[cur_idx] = NULL;
449 + }
450 + rfi->pktslots[cur_idx] = pkt;
451 + rfi->pend_pkts++;
452 +
453 + /* got the expected one. flush from current to expected
454 + * and update expected
455 + */
456 + brcmf_dbg(DATA, "flow-%d: expected %d (%d), pending %d\n",
457 + flow_id, cur_idx, exp_idx, rfi->pend_pkts);
458 +
459 + rfi->cur_idx = cur_idx;
460 + rfi->exp_idx = exp_idx;
461 +
462 + brcmf_rxreorder_get_skb_list(rfi, cur_idx, exp_idx,
463 + &reorder_list);
464 + brcmf_dbg(DATA, "flow-%d: freeing buffers %d, pending %d\n",
465 + flow_id, skb_queue_len(&reorder_list),
466 + rfi->pend_pkts);
467 + } else {
468 + u8 end_idx;
469 +
470 + brcmf_dbg(DATA, "flow-%d (0x%x): both moved, old %d/%d, new %d/%d\n",
471 + flow_id, flags, rfi->cur_idx, rfi->exp_idx,
472 + cur_idx, exp_idx);
473 + if (flags & BRCMF_RXREORDER_FLUSH_ALL)
474 + end_idx = rfi->exp_idx;
475 + else
476 + end_idx = exp_idx;
477 +
478 + /* flush pkts first */
479 + brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
480 + &reorder_list);
481 +
482 + if (exp_idx == ((cur_idx + 1) % (rfi->max_idx + 1))) {
483 + __skb_queue_tail(&reorder_list, pkt);
484 + } else {
485 + rfi->pktslots[cur_idx] = pkt;
486 + rfi->pend_pkts++;
487 + }
488 + rfi->exp_idx = exp_idx;
489 + rfi->cur_idx = cur_idx;
490 + }
491 + } else {
492 + /* explicity window move updating the expected index */
493 + exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
494 +
495 + brcmf_dbg(DATA, "flow-%d (0x%x): change expected: %d -> %d\n",
496 + flow_id, flags, rfi->exp_idx, exp_idx);
497 + if (flags & BRCMF_RXREORDER_FLUSH_ALL)
498 + end_idx = rfi->exp_idx;
499 + else
500 + end_idx = exp_idx;
501 +
502 + brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
503 + &reorder_list);
504 + __skb_queue_tail(&reorder_list, pkt);
505 + /* set the new expected idx */
506 + rfi->exp_idx = exp_idx;
507 + }
508 +netif_rx:
509 + skb_queue_walk_safe(&reorder_list, pkt, pnext) {
510 + __skb_unlink(pkt, &reorder_list);
511 + brcmf_netif_rx(ifp, pkt, false);
512 + }
513 +}
514 +
515 void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb)
516 {
517 struct brcmf_skb_reorder_data *rd;
518 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
519 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
520 @@ -29,5 +29,6 @@ void brcmf_fws_add_interface(struct brcm
521 void brcmf_fws_del_interface(struct brcmf_if *ifp);
522 void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb);
523 void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked);
524 +void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb);
525
526 #endif /* FWSIGNAL_H_ */
527 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
528 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
529 @@ -527,6 +527,9 @@ static int brcmf_msgbuf_hdrpull(struct b
530 return -ENODEV;
531 }
532
533 +static void brcmf_msgbuf_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb)
534 +{
535 +}
536
537 static void
538 brcmf_msgbuf_remove_flowring(struct brcmf_msgbuf *msgbuf, u16 flowid)
539 @@ -1466,6 +1469,7 @@ int brcmf_proto_msgbuf_attach(struct brc
540 drvr->proto->configure_addr_mode = brcmf_msgbuf_configure_addr_mode;
541 drvr->proto->delete_peer = brcmf_msgbuf_delete_peer;
542 drvr->proto->add_tdls_peer = brcmf_msgbuf_add_tdls_peer;
543 + drvr->proto->rxreorder = brcmf_msgbuf_rxreorder;
544 drvr->proto->pd = msgbuf;
545
546 init_waitqueue_head(&msgbuf->ioctl_resp_wait);
547 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
548 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
549 @@ -22,6 +22,9 @@ enum proto_addr_mode {
550 ADDR_DIRECT
551 };
552
553 +struct brcmf_skb_reorder_data {
554 + u8 *reorder;
555 +};
556
557 struct brcmf_proto {
558 int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws,
559 @@ -38,6 +41,7 @@ struct brcmf_proto {
560 u8 peer[ETH_ALEN]);
561 void (*add_tdls_peer)(struct brcmf_pub *drvr, int ifidx,
562 u8 peer[ETH_ALEN]);
563 + void (*rxreorder)(struct brcmf_if *ifp, struct sk_buff *skb);
564 void *pd;
565 };
566
567 @@ -91,6 +95,18 @@ brcmf_proto_add_tdls_peer(struct brcmf_p
568 {
569 drvr->proto->add_tdls_peer(drvr, ifidx, peer);
570 }
571 +static inline bool brcmf_proto_is_reorder_skb(struct sk_buff *skb)
572 +{
573 + struct brcmf_skb_reorder_data *rd;
574 +
575 + rd = (struct brcmf_skb_reorder_data *)skb->cb;
576 + return !!rd->reorder;
577 +}
578
579 +static inline void
580 +brcmf_proto_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb)
581 +{
582 + ifp->drvr->proto->rxreorder(ifp, skb);
583 +}
584
585 #endif /* BRCMFMAC_PROTO_H */