349-0006-brcmfmac-cleanup-ampdu-rx-host-reorder-code.patch 18 KB

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