/drivers/staging/rtl8712/rtl8712_recv.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2 · C · 1131 lines · 915 code · 61 blank · 155 comment · 226 complexity · 58eaf99e8d5750688e2c8fa094f7d909 MD5 · raw file

  1. /******************************************************************************
  2. * rtl8712_recv.c
  3. *
  4. * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
  5. * Linux device driver for RTL8192SU
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of version 2 of the GNU General Public License as
  9. * published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  14. * more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along with
  17. * this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  19. *
  20. * Modifications for inclusion into the Linux staging tree are
  21. * Copyright(c) 2010 Larry Finger. All rights reserved.
  22. *
  23. * Contact information:
  24. * WLAN FAE <wlanfae@realtek.com>
  25. * Larry Finger <Larry.Finger@lwfinger.net>
  26. *
  27. ******************************************************************************/
  28. #define _RTL8712_RECV_C_
  29. #include "osdep_service.h"
  30. #include "drv_types.h"
  31. #include "recv_osdep.h"
  32. #include "mlme_osdep.h"
  33. #include "ip.h"
  34. #include "if_ether.h"
  35. #include "ethernet.h"
  36. #include "usb_ops.h"
  37. #include "wifi.h"
  38. /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
  39. static u8 bridge_tunnel_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
  40. /* Ethernet-II snap header (RFC1042 for most EtherTypes) */
  41. static u8 rfc1042_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
  42. static void recv_tasklet(void *priv);
  43. int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter)
  44. {
  45. int i;
  46. struct recv_buf *precvbuf;
  47. int res = _SUCCESS;
  48. addr_t tmpaddr = 0;
  49. int alignment = 0;
  50. struct sk_buff *pskb = NULL;
  51. sema_init(&precvpriv->recv_sema, 0);
  52. sema_init(&precvpriv->terminate_recvthread_sema, 0);
  53. /*init recv_buf*/
  54. _init_queue(&precvpriv->free_recv_buf_queue);
  55. precvpriv->pallocated_recv_buf = _malloc(NR_RECVBUFF *
  56. sizeof(struct recv_buf) + 4);
  57. if (precvpriv->pallocated_recv_buf == NULL)
  58. return _FAIL;
  59. memset(precvpriv->pallocated_recv_buf, 0, NR_RECVBUFF *
  60. sizeof(struct recv_buf) + 4);
  61. precvpriv->precv_buf = precvpriv->pallocated_recv_buf + 4 -
  62. ((addr_t) (precvpriv->pallocated_recv_buf) & 3);
  63. precvbuf = (struct recv_buf *)precvpriv->precv_buf;
  64. for (i = 0; i < NR_RECVBUFF; i++) {
  65. _init_listhead(&precvbuf->list);
  66. spin_lock_init(&precvbuf->recvbuf_lock);
  67. res = r8712_os_recvbuf_resource_alloc(padapter, precvbuf);
  68. if (res == _FAIL)
  69. break;
  70. precvbuf->ref_cnt = 0;
  71. precvbuf->adapter = padapter;
  72. list_insert_tail(&precvbuf->list,
  73. &(precvpriv->free_recv_buf_queue.queue));
  74. precvbuf++;
  75. }
  76. precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
  77. tasklet_init(&precvpriv->recv_tasklet,
  78. (void(*)(unsigned long))recv_tasklet,
  79. (unsigned long)padapter);
  80. skb_queue_head_init(&precvpriv->rx_skb_queue);
  81. skb_queue_head_init(&precvpriv->free_recv_skb_queue);
  82. for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) {
  83. pskb = netdev_alloc_skb(padapter->pnetdev, MAX_RECVBUF_SZ +
  84. RECVBUFF_ALIGN_SZ);
  85. if (pskb) {
  86. pskb->dev = padapter->pnetdev;
  87. tmpaddr = (addr_t)pskb->data;
  88. alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
  89. skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
  90. skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
  91. }
  92. pskb = NULL;
  93. }
  94. return res;
  95. }
  96. void r8712_free_recv_priv(struct recv_priv *precvpriv)
  97. {
  98. int i;
  99. struct recv_buf *precvbuf;
  100. struct _adapter *padapter = precvpriv->adapter;
  101. precvbuf = (struct recv_buf *)precvpriv->precv_buf;
  102. for (i = 0; i < NR_RECVBUFF ; i++) {
  103. r8712_os_recvbuf_resource_free(padapter, precvbuf);
  104. precvbuf++;
  105. }
  106. kfree(precvpriv->pallocated_recv_buf);
  107. skb_queue_purge(&precvpriv->rx_skb_queue);
  108. if (skb_queue_len(&precvpriv->rx_skb_queue))
  109. printk(KERN_WARNING "r8712u: rx_skb_queue not empty\n");
  110. skb_queue_purge(&precvpriv->free_recv_skb_queue);
  111. if (skb_queue_len(&precvpriv->free_recv_skb_queue))
  112. printk(KERN_WARNING "r8712u: free_recv_skb_queue not empty "
  113. "%d\n", skb_queue_len(&precvpriv->free_recv_skb_queue));
  114. }
  115. int r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf)
  116. {
  117. int res = _SUCCESS;
  118. precvbuf->transfer_len = 0;
  119. precvbuf->len = 0;
  120. precvbuf->ref_cnt = 0;
  121. if (precvbuf->pbuf) {
  122. precvbuf->pdata = precvbuf->pbuf;
  123. precvbuf->phead = precvbuf->pbuf;
  124. precvbuf->ptail = precvbuf->pbuf;
  125. precvbuf->pend = precvbuf->pdata + MAX_RECVBUF_SZ;
  126. }
  127. return res;
  128. }
  129. int r8712_free_recvframe(union recv_frame *precvframe,
  130. struct __queue *pfree_recv_queue)
  131. {
  132. unsigned long irqL;
  133. struct _adapter *padapter = precvframe->u.hdr.adapter;
  134. struct recv_priv *precvpriv = &padapter->recvpriv;
  135. if (precvframe->u.hdr.pkt) {
  136. dev_kfree_skb_any(precvframe->u.hdr.pkt);/*free skb by driver*/
  137. precvframe->u.hdr.pkt = NULL;
  138. }
  139. spin_lock_irqsave(&pfree_recv_queue->lock, irqL);
  140. list_delete(&(precvframe->u.hdr.list));
  141. list_insert_tail(&(precvframe->u.hdr.list),
  142. get_list_head(pfree_recv_queue));
  143. if (padapter != NULL) {
  144. if (pfree_recv_queue == &precvpriv->free_recv_queue)
  145. precvpriv->free_recvframe_cnt++;
  146. }
  147. spin_unlock_irqrestore(&pfree_recv_queue->lock, irqL);
  148. return _SUCCESS;
  149. }
  150. static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib,
  151. struct recv_stat *prxstat)
  152. {
  153. u32 *pphy_info;
  154. struct phy_stat *pphy_stat;
  155. u16 drvinfo_sz = 0;
  156. drvinfo_sz = (le32_to_cpu(prxstat->rxdw0)&0x000f0000)>>16;
  157. drvinfo_sz = drvinfo_sz<<3;
  158. /*TODO:
  159. * Offset 0 */
  160. pattrib->bdecrypted = ((le32_to_cpu(prxstat->rxdw0) & BIT(27)) >> 27)
  161. ? 0 : 1;
  162. pattrib->crc_err = ((le32_to_cpu(prxstat->rxdw0) & BIT(14)) >> 14);
  163. /*Offset 4*/
  164. /*Offset 8*/
  165. /*Offset 12*/
  166. if (le32_to_cpu(prxstat->rxdw3) & BIT(13)) {
  167. pattrib->tcpchk_valid = 1; /* valid */
  168. if (le32_to_cpu(prxstat->rxdw3) & BIT(11))
  169. pattrib->tcp_chkrpt = 1; /* correct */
  170. else
  171. pattrib->tcp_chkrpt = 0; /* incorrect */
  172. if (le32_to_cpu(prxstat->rxdw3) & BIT(12))
  173. pattrib->ip_chkrpt = 1; /* correct */
  174. else
  175. pattrib->ip_chkrpt = 0; /* incorrect */
  176. } else
  177. pattrib->tcpchk_valid = 0; /* invalid */
  178. pattrib->mcs_rate = (u8)((le32_to_cpu(prxstat->rxdw3)) & 0x3f);
  179. pattrib->htc = (u8)((le32_to_cpu(prxstat->rxdw3) >> 6) & 0x1);
  180. /*Offset 16*/
  181. /*Offset 20*/
  182. /*phy_info*/
  183. if (drvinfo_sz) {
  184. pphy_stat = (struct phy_stat *)(prxstat+1);
  185. pphy_info = (u32 *)prxstat+1;
  186. }
  187. }
  188. /*perform defrag*/
  189. static union recv_frame *recvframe_defrag(struct _adapter *adapter,
  190. struct __queue *defrag_q)
  191. {
  192. struct list_head *plist, *phead;
  193. u8 wlanhdr_offset;
  194. u8 curfragnum;
  195. struct recv_frame_hdr *pfhdr, *pnfhdr;
  196. union recv_frame *prframe, *pnextrframe;
  197. struct __queue *pfree_recv_queue;
  198. pfree_recv_queue = &adapter->recvpriv.free_recv_queue;
  199. phead = get_list_head(defrag_q);
  200. plist = get_next(phead);
  201. prframe = LIST_CONTAINOR(plist, union recv_frame, u);
  202. list_delete(&prframe->u.list);
  203. pfhdr = &prframe->u.hdr;
  204. curfragnum = 0;
  205. if (curfragnum != pfhdr->attrib.frag_num) {
  206. /*the first fragment number must be 0
  207. *free the whole queue*/
  208. r8712_free_recvframe(prframe, pfree_recv_queue);
  209. prframe = NULL;
  210. goto exit;
  211. }
  212. plist = get_next(phead);
  213. while (end_of_queue_search(phead, plist) == false) {
  214. pnextrframe = LIST_CONTAINOR(plist, union recv_frame, u);
  215. /*check the fragment sequence (2nd ~n fragment frame) */
  216. pnfhdr = &pnextrframe->u.hdr;
  217. curfragnum++;
  218. if (curfragnum != pnfhdr->attrib.frag_num) {
  219. /* the fragment number must increase (after decache)
  220. * release the defrag_q & prframe */
  221. r8712_free_recvframe(prframe, pfree_recv_queue);
  222. prframe = NULL;
  223. goto exit;
  224. }
  225. /* copy the 2nd~n fragment frame's payload to the first fragment
  226. * get the 2nd~last fragment frame's payload */
  227. wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
  228. recvframe_pull(pnextrframe, wlanhdr_offset);
  229. /* append to first fragment frame's tail (if privacy frame,
  230. * pull the ICV) */
  231. recvframe_pull_tail(prframe, pfhdr->attrib.icv_len);
  232. memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len);
  233. recvframe_put(prframe, pnfhdr->len);
  234. pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;
  235. plist = get_next(plist);
  236. }
  237. exit:
  238. /* free the defrag_q queue and return the prframe */
  239. r8712_free_recvframe_queue(defrag_q, pfree_recv_queue);
  240. return prframe;
  241. }
  242. /* check if need to defrag, if needed queue the frame to defrag_q */
  243. union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter,
  244. union recv_frame *precv_frame)
  245. {
  246. u8 ismfrag;
  247. u8 fragnum;
  248. u8 *psta_addr;
  249. struct recv_frame_hdr *pfhdr;
  250. struct sta_info *psta;
  251. struct sta_priv *pstapriv ;
  252. struct list_head *phead;
  253. union recv_frame *prtnframe = NULL;
  254. struct __queue *pfree_recv_queue, *pdefrag_q;
  255. pstapriv = &padapter->stapriv;
  256. pfhdr = &precv_frame->u.hdr;
  257. pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
  258. /* need to define struct of wlan header frame ctrl */
  259. ismfrag = pfhdr->attrib.mfrag;
  260. fragnum = pfhdr->attrib.frag_num;
  261. psta_addr = pfhdr->attrib.ta;
  262. psta = r8712_get_stainfo(pstapriv, psta_addr);
  263. if (psta == NULL)
  264. pdefrag_q = NULL;
  265. else
  266. pdefrag_q = &psta->sta_recvpriv.defrag_q;
  267. if ((ismfrag == 0) && (fragnum == 0))
  268. prtnframe = precv_frame;/*isn't a fragment frame*/
  269. if (ismfrag == 1) {
  270. /* 0~(n-1) fragment frame
  271. * enqueue to defraf_g */
  272. if (pdefrag_q != NULL) {
  273. if (fragnum == 0) {
  274. /*the first fragment*/
  275. if (_queue_empty(pdefrag_q) == false) {
  276. /*free current defrag_q */
  277. r8712_free_recvframe_queue(pdefrag_q,
  278. pfree_recv_queue);
  279. }
  280. }
  281. /* Then enqueue the 0~(n-1) fragment to the defrag_q */
  282. phead = get_list_head(pdefrag_q);
  283. list_insert_tail(&pfhdr->list, phead);
  284. prtnframe = NULL;
  285. } else {
  286. /* can't find this ta's defrag_queue, so free this
  287. * recv_frame */
  288. r8712_free_recvframe(precv_frame, pfree_recv_queue);
  289. prtnframe = NULL;
  290. }
  291. }
  292. if ((ismfrag == 0) && (fragnum != 0)) {
  293. /* the last fragment frame
  294. * enqueue the last fragment */
  295. if (pdefrag_q != NULL) {
  296. phead = get_list_head(pdefrag_q);
  297. list_insert_tail(&pfhdr->list, phead);
  298. /*call recvframe_defrag to defrag*/
  299. precv_frame = recvframe_defrag(padapter, pdefrag_q);
  300. prtnframe = precv_frame;
  301. } else {
  302. /* can't find this ta's defrag_queue, so free this
  303. * recv_frame */
  304. r8712_free_recvframe(precv_frame, pfree_recv_queue);
  305. prtnframe = NULL;
  306. }
  307. }
  308. if ((prtnframe != NULL) && (prtnframe->u.hdr.attrib.privacy)) {
  309. /* after defrag we must check tkip mic code */
  310. if (r8712_recvframe_chkmic(padapter, prtnframe) == _FAIL) {
  311. r8712_free_recvframe(prtnframe, pfree_recv_queue);
  312. prtnframe = NULL;
  313. }
  314. }
  315. return prtnframe;
  316. }
  317. static int amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe)
  318. {
  319. int a_len, padding_len;
  320. u16 eth_type, nSubframe_Length;
  321. u8 nr_subframes, i;
  322. unsigned char *data_ptr, *pdata;
  323. struct rx_pkt_attrib *pattrib;
  324. _pkt *sub_skb, *subframes[MAX_SUBFRAME_COUNT];
  325. struct recv_priv *precvpriv = &padapter->recvpriv;
  326. struct __queue *pfree_recv_queue = &(precvpriv->free_recv_queue);
  327. int ret = _SUCCESS;
  328. nr_subframes = 0;
  329. pattrib = &prframe->u.hdr.attrib;
  330. recvframe_pull(prframe, prframe->u.hdr.attrib.hdrlen);
  331. if (prframe->u.hdr.attrib.iv_len > 0)
  332. recvframe_pull(prframe, prframe->u.hdr.attrib.iv_len);
  333. a_len = prframe->u.hdr.len;
  334. pdata = prframe->u.hdr.rx_data;
  335. while (a_len > ETH_HLEN) {
  336. /* Offset 12 denote 2 mac address */
  337. nSubframe_Length = *((u16 *)(pdata + 12));
  338. /*==m==>change the length order*/
  339. nSubframe_Length = (nSubframe_Length >> 8) +
  340. (nSubframe_Length << 8);
  341. if (a_len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) {
  342. printk(KERN_WARNING "r8712u: nRemain_Length is %d and"
  343. " nSubframe_Length is: %d\n",
  344. a_len, nSubframe_Length);
  345. goto exit;
  346. }
  347. /* move the data point to data content */
  348. pdata += ETH_HLEN;
  349. a_len -= ETH_HLEN;
  350. /* Allocate new skb for releasing to upper layer */
  351. sub_skb = dev_alloc_skb(nSubframe_Length + 12);
  352. skb_reserve(sub_skb, 12);
  353. data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length);
  354. memcpy(data_ptr, pdata, nSubframe_Length);
  355. subframes[nr_subframes++] = sub_skb;
  356. if (nr_subframes >= MAX_SUBFRAME_COUNT) {
  357. printk(KERN_WARNING "r8712u: ParseSubframe(): Too"
  358. " many Subframes! Packets dropped!\n");
  359. break;
  360. }
  361. pdata += nSubframe_Length;
  362. a_len -= nSubframe_Length;
  363. if (a_len != 0) {
  364. padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & 3);
  365. if (padding_len == 4)
  366. padding_len = 0;
  367. if (a_len < padding_len)
  368. goto exit;
  369. pdata += padding_len;
  370. a_len -= padding_len;
  371. }
  372. }
  373. for (i = 0; i < nr_subframes; i++) {
  374. sub_skb = subframes[i];
  375. /* convert hdr + possible LLC headers into Ethernet header */
  376. eth_type = (sub_skb->data[6] << 8) | sub_skb->data[7];
  377. if (sub_skb->len >= 8 &&
  378. ((!memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) &&
  379. eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
  380. !memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE))) {
  381. /* remove RFC1042 or Bridge-Tunnel encapsulation and
  382. * replace EtherType */
  383. skb_pull(sub_skb, SNAP_SIZE);
  384. memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src,
  385. ETH_ALEN);
  386. memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst,
  387. ETH_ALEN);
  388. } else {
  389. u16 len;
  390. /* Leave Ethernet header part of hdr and full payload */
  391. len = htons(sub_skb->len);
  392. memcpy(skb_push(sub_skb, 2), &len, 2);
  393. memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src,
  394. ETH_ALEN);
  395. memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst,
  396. ETH_ALEN);
  397. }
  398. /* Indicate the packets to upper layer */
  399. if (sub_skb) {
  400. sub_skb->protocol =
  401. eth_type_trans(sub_skb, padapter->pnetdev);
  402. sub_skb->dev = padapter->pnetdev;
  403. if ((pattrib->tcpchk_valid == 1) &&
  404. (pattrib->tcp_chkrpt == 1)) {
  405. sub_skb->ip_summed = CHECKSUM_UNNECESSARY;
  406. } else
  407. sub_skb->ip_summed = CHECKSUM_NONE;
  408. netif_rx(sub_skb);
  409. }
  410. }
  411. exit:
  412. prframe->u.hdr.len = 0;
  413. r8712_free_recvframe(prframe, pfree_recv_queue);
  414. return ret;
  415. }
  416. void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf)
  417. {
  418. uint voffset;
  419. u8 *poffset;
  420. u16 pkt_len, cmd_len, drvinfo_sz;
  421. u8 eid, cmd_seq;
  422. struct recv_stat *prxstat;
  423. poffset = (u8 *)prxcmdbuf;
  424. voffset = *(uint *)poffset;
  425. pkt_len = le32_to_cpu(voffset) & 0x00003fff;
  426. prxstat = (struct recv_stat *)prxcmdbuf;
  427. drvinfo_sz = ((le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16);
  428. drvinfo_sz = drvinfo_sz << 3;
  429. poffset += RXDESC_SIZE + drvinfo_sz;
  430. do {
  431. voffset = *(uint *)poffset;
  432. cmd_len = (u16)(le32_to_cpu(voffset) & 0xffff);
  433. cmd_seq = (u8)((le32_to_cpu(voffset) >> 24) & 0x7f);
  434. eid = (u8)((le32_to_cpu(voffset) >> 16) & 0xff);
  435. r8712_event_handle(padapter, (uint *)poffset);
  436. poffset += (cmd_len + 8);/*8 bytes aligment*/
  437. } while (le32_to_cpu(voffset) & BIT(31));
  438. }
  439. static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl,
  440. u16 seq_num)
  441. {
  442. u8 wsize = preorder_ctrl->wsize_b;
  443. u16 wend = (preorder_ctrl->indicate_seq + wsize - 1) % 4096;
  444. /* Rx Reorder initialize condition.*/
  445. if (preorder_ctrl->indicate_seq == 0xffff)
  446. preorder_ctrl->indicate_seq = seq_num;
  447. /* Drop out the packet which SeqNum is smaller than WinStart */
  448. if (SN_LESS(seq_num, preorder_ctrl->indicate_seq))
  449. return false;
  450. /*
  451. * Sliding window manipulation. Conditions includes:
  452. * 1. Incoming SeqNum is equal to WinStart =>Window shift 1
  453. * 2. Incoming SeqNum is larger than the WinEnd => Window shift N
  454. */
  455. if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq))
  456. preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq +
  457. 1) % 4096;
  458. else if (SN_LESS(wend, seq_num)) {
  459. if (seq_num >= (wsize - 1))
  460. preorder_ctrl->indicate_seq = seq_num + 1 - wsize;
  461. else
  462. preorder_ctrl->indicate_seq = 4095 - (wsize -
  463. (seq_num + 1)) + 1;
  464. }
  465. return true;
  466. }
  467. static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl,
  468. union recv_frame *prframe)
  469. {
  470. struct list_head *phead, *plist;
  471. union recv_frame *pnextrframe;
  472. struct rx_pkt_attrib *pnextattrib;
  473. struct __queue *ppending_recvframe_queue =
  474. &preorder_ctrl->pending_recvframe_queue;
  475. struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
  476. phead = get_list_head(ppending_recvframe_queue);
  477. plist = get_next(phead);
  478. while (end_of_queue_search(phead, plist) == false) {
  479. pnextrframe = LIST_CONTAINOR(plist, union recv_frame, u);
  480. pnextattrib = &pnextrframe->u.hdr.attrib;
  481. if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num))
  482. plist = get_next(plist);
  483. else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num))
  484. return false;
  485. else
  486. break;
  487. }
  488. list_delete(&(prframe->u.hdr.list));
  489. list_insert_tail(&(prframe->u.hdr.list), plist);
  490. return true;
  491. }
  492. int r8712_recv_indicatepkts_in_order(struct _adapter *padapter,
  493. struct recv_reorder_ctrl *preorder_ctrl,
  494. int bforced)
  495. {
  496. struct list_head *phead, *plist;
  497. union recv_frame *prframe;
  498. struct rx_pkt_attrib *pattrib;
  499. int bPktInBuf = false;
  500. struct recv_priv *precvpriv = &padapter->recvpriv;
  501. struct __queue *ppending_recvframe_queue =
  502. &preorder_ctrl->pending_recvframe_queue;
  503. phead = get_list_head(ppending_recvframe_queue);
  504. plist = get_next(phead);
  505. /* Handling some condition for forced indicate case.*/
  506. if (bforced == true) {
  507. if (is_list_empty(phead))
  508. return true;
  509. else {
  510. prframe = LIST_CONTAINOR(plist, union recv_frame, u);
  511. pattrib = &prframe->u.hdr.attrib;
  512. preorder_ctrl->indicate_seq = pattrib->seq_num;
  513. }
  514. }
  515. /* Prepare indication list and indication.
  516. * Check if there is any packet need indicate. */
  517. while (!is_list_empty(phead)) {
  518. prframe = LIST_CONTAINOR(plist, union recv_frame, u);
  519. pattrib = &prframe->u.hdr.attrib;
  520. if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
  521. plist = get_next(plist);
  522. list_delete(&(prframe->u.hdr.list));
  523. if (SN_EQUAL(preorder_ctrl->indicate_seq,
  524. pattrib->seq_num))
  525. preorder_ctrl->indicate_seq =
  526. (preorder_ctrl->indicate_seq + 1) % 4096;
  527. /*indicate this recv_frame*/
  528. if (!pattrib->amsdu) {
  529. if ((padapter->bDriverStopped == false) &&
  530. (padapter->bSurpriseRemoved == false)) {
  531. /* indicate this recv_frame */
  532. r8712_recv_indicatepkt(padapter,
  533. prframe);
  534. }
  535. } else if (pattrib->amsdu == 1) {
  536. if (amsdu_to_msdu(padapter, prframe) !=
  537. _SUCCESS)
  538. r8712_free_recvframe(prframe,
  539. &precvpriv->free_recv_queue);
  540. }
  541. /* Update local variables. */
  542. bPktInBuf = false;
  543. } else {
  544. bPktInBuf = true;
  545. break;
  546. }
  547. }
  548. return bPktInBuf;
  549. }
  550. static int recv_indicatepkt_reorder(struct _adapter *padapter,
  551. union recv_frame *prframe)
  552. {
  553. unsigned long irql;
  554. struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
  555. struct recv_reorder_ctrl *preorder_ctrl = prframe->u.hdr.preorder_ctrl;
  556. struct __queue *ppending_recvframe_queue =
  557. &preorder_ctrl->pending_recvframe_queue;
  558. if (!pattrib->amsdu) {
  559. /* s1. */
  560. r8712_wlanhdr_to_ethhdr(prframe);
  561. if (pattrib->qos != 1) {
  562. if ((padapter->bDriverStopped == false) &&
  563. (padapter->bSurpriseRemoved == false)) {
  564. r8712_recv_indicatepkt(padapter, prframe);
  565. return _SUCCESS;
  566. } else
  567. return _FAIL;
  568. }
  569. }
  570. spin_lock_irqsave(&ppending_recvframe_queue->lock, irql);
  571. /*s2. check if winstart_b(indicate_seq) needs to been updated*/
  572. if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num))
  573. goto _err_exit;
  574. /*s3. Insert all packet into Reorder Queue to maintain its ordering.*/
  575. if (!enqueue_reorder_recvframe(preorder_ctrl, prframe))
  576. goto _err_exit;
  577. /*s4.
  578. * Indication process.
  579. * After Packet dropping and Sliding Window shifting as above, we can
  580. * now just indicate the packets with the SeqNum smaller than latest
  581. * WinStart and buffer other packets.
  582. *
  583. * For Rx Reorder condition:
  584. * 1. All packets with SeqNum smaller than WinStart => Indicate
  585. * 2. All packets with SeqNum larger than or equal to
  586. * WinStart => Buffer it.
  587. */
  588. if (r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, false) ==
  589. true) {
  590. _set_timer(&preorder_ctrl->reordering_ctrl_timer,
  591. REORDER_WAIT_TIME);
  592. spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
  593. } else {
  594. spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
  595. _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
  596. }
  597. return _SUCCESS;
  598. _err_exit:
  599. spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
  600. return _FAIL;
  601. }
  602. void r8712_reordering_ctrl_timeout_handler(void *pcontext)
  603. {
  604. unsigned long irql;
  605. struct recv_reorder_ctrl *preorder_ctrl =
  606. (struct recv_reorder_ctrl *)pcontext;
  607. struct _adapter *padapter = preorder_ctrl->padapter;
  608. struct __queue *ppending_recvframe_queue =
  609. &preorder_ctrl->pending_recvframe_queue;
  610. if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
  611. return;
  612. spin_lock_irqsave(&ppending_recvframe_queue->lock, irql);
  613. r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, true);
  614. spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
  615. }
  616. static int r8712_process_recv_indicatepkts(struct _adapter *padapter,
  617. union recv_frame *prframe)
  618. {
  619. int retval = _SUCCESS;
  620. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  621. struct ht_priv *phtpriv = &pmlmepriv->htpriv;
  622. if (phtpriv->ht_option == 1) { /*B/G/N Mode*/
  623. if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) {
  624. /* including perform A-MPDU Rx Ordering Buffer Control*/
  625. if ((padapter->bDriverStopped == false) &&
  626. (padapter->bSurpriseRemoved == false))
  627. return _FAIL;
  628. }
  629. } else { /*B/G mode*/
  630. retval = r8712_wlanhdr_to_ethhdr(prframe);
  631. if (retval != _SUCCESS)
  632. return retval;
  633. if ((padapter->bDriverStopped == false) &&
  634. (padapter->bSurpriseRemoved == false)) {
  635. /* indicate this recv_frame */
  636. r8712_recv_indicatepkt(padapter, prframe);
  637. } else
  638. return _FAIL;
  639. }
  640. return retval;
  641. }
  642. static u8 query_rx_pwr_percentage(s8 antpower)
  643. {
  644. if ((antpower <= -100) || (antpower >= 20))
  645. return 0;
  646. else if (antpower >= 0)
  647. return 100;
  648. else
  649. return 100 + antpower;
  650. }
  651. static u8 evm_db2percentage(s8 value)
  652. {
  653. /*
  654. * -33dB~0dB to 0%~99%
  655. */
  656. s8 ret_val;
  657. ret_val = value;
  658. if (ret_val >= 0)
  659. ret_val = 0;
  660. if (ret_val <= -33)
  661. ret_val = -33;
  662. ret_val = -ret_val;
  663. ret_val *= 3;
  664. if (ret_val == 99)
  665. ret_val = 100;
  666. return ret_val;
  667. }
  668. s32 r8712_signal_scale_mapping(s32 cur_sig)
  669. {
  670. s32 ret_sig;
  671. if (cur_sig >= 51 && cur_sig <= 100)
  672. ret_sig = 100;
  673. else if (cur_sig >= 41 && cur_sig <= 50)
  674. ret_sig = 80 + ((cur_sig - 40) * 2);
  675. else if (cur_sig >= 31 && cur_sig <= 40)
  676. ret_sig = 66 + (cur_sig - 30);
  677. else if (cur_sig >= 21 && cur_sig <= 30)
  678. ret_sig = 54 + (cur_sig - 20);
  679. else if (cur_sig >= 10 && cur_sig <= 20)
  680. ret_sig = 42 + (((cur_sig - 10) * 2) / 3);
  681. else if (cur_sig >= 5 && cur_sig <= 9)
  682. ret_sig = 22 + (((cur_sig - 5) * 3) / 2);
  683. else if (cur_sig >= 1 && cur_sig <= 4)
  684. ret_sig = 6 + (((cur_sig - 1) * 3) / 2);
  685. else
  686. ret_sig = cur_sig;
  687. return ret_sig;
  688. }
  689. static s32 translate2dbm(struct _adapter *padapter, u8 signal_strength_idx)
  690. {
  691. s32 signal_power; /* in dBm.*/
  692. /* Translate to dBm (x=0.5y-95).*/
  693. signal_power = (s32)((signal_strength_idx + 1) >> 1);
  694. signal_power -= 95;
  695. return signal_power;
  696. }
  697. static void query_rx_phy_status(struct _adapter *padapter,
  698. union recv_frame *prframe)
  699. {
  700. u8 i, max_spatial_stream, evm;
  701. struct recv_stat *prxstat = (struct recv_stat *)prframe->u.hdr.rx_head;
  702. struct phy_stat *pphy_stat = (struct phy_stat *)(prxstat + 1);
  703. u8 *pphy_head = (u8 *)(prxstat + 1);
  704. s8 rx_pwr[4], rx_pwr_all;
  705. u8 pwdb_all;
  706. u32 rssi, total_rssi = 0;
  707. u8 bcck_rate = 0, rf_rx_num = 0, cck_highpwr = 0;
  708. struct phy_cck_rx_status *pcck_buf;
  709. u8 sq;
  710. /* Record it for next packet processing*/
  711. bcck_rate = (prframe->u.hdr.attrib.mcs_rate <= 3 ? 1 : 0);
  712. if (bcck_rate) {
  713. u8 report;
  714. /* CCK Driver info Structure is not the same as OFDM packet.*/
  715. pcck_buf = (struct phy_cck_rx_status *)pphy_stat;
  716. /* (1)Hardware does not provide RSSI for CCK
  717. * (2)PWDB, Average PWDB cacluated by hardware
  718. * (for rate adaptive)
  719. */
  720. if (!cck_highpwr) {
  721. report = pcck_buf->cck_agc_rpt & 0xc0;
  722. report = report >> 6;
  723. switch (report) {
  724. /* Modify the RF RNA gain value to -40, -20,
  725. * -2, 14 by Jenyu's suggestion
  726. * Note: different RF with the different
  727. * RNA gain. */
  728. case 0x3:
  729. rx_pwr_all = -40 - (pcck_buf->cck_agc_rpt &
  730. 0x3e);
  731. break;
  732. case 0x2:
  733. rx_pwr_all = -20 - (pcck_buf->cck_agc_rpt &
  734. 0x3e);
  735. break;
  736. case 0x1:
  737. rx_pwr_all = -2 - (pcck_buf->cck_agc_rpt &
  738. 0x3e);
  739. break;
  740. case 0x0:
  741. rx_pwr_all = 14 - (pcck_buf->cck_agc_rpt &
  742. 0x3e);
  743. break;
  744. }
  745. } else {
  746. report = ((u8)(le32_to_cpu(pphy_stat->phydw1) >> 8)) &
  747. 0x60;
  748. report = report >> 5;
  749. switch (report) {
  750. case 0x3:
  751. rx_pwr_all = -40 - ((pcck_buf->cck_agc_rpt &
  752. 0x1f) << 1);
  753. break;
  754. case 0x2:
  755. rx_pwr_all = -20 - ((pcck_buf->cck_agc_rpt &
  756. 0x1f) << 1);
  757. break;
  758. case 0x1:
  759. rx_pwr_all = -2 - ((pcck_buf->cck_agc_rpt &
  760. 0x1f) << 1);
  761. break;
  762. case 0x0:
  763. rx_pwr_all = 14 - ((pcck_buf->cck_agc_rpt &
  764. 0x1f) << 1);
  765. break;
  766. }
  767. }
  768. pwdb_all = query_rx_pwr_percentage(rx_pwr_all);
  769. /* CCK gain is smaller than OFDM/MCS gain,*/
  770. /* so we add gain diff by experiences, the val is 6 */
  771. pwdb_all += 6;
  772. if (pwdb_all > 100)
  773. pwdb_all = 100;
  774. /* modify the offset to make the same gain index with OFDM.*/
  775. if (pwdb_all > 34 && pwdb_all <= 42)
  776. pwdb_all -= 2;
  777. else if (pwdb_all > 26 && pwdb_all <= 34)
  778. pwdb_all -= 6;
  779. else if (pwdb_all > 14 && pwdb_all <= 26)
  780. pwdb_all -= 8;
  781. else if (pwdb_all > 4 && pwdb_all <= 14)
  782. pwdb_all -= 4;
  783. /*
  784. * (3) Get Signal Quality (EVM)
  785. */
  786. if (pwdb_all > 40)
  787. sq = 100;
  788. else {
  789. sq = pcck_buf->sq_rpt;
  790. if (pcck_buf->sq_rpt > 64)
  791. sq = 0;
  792. else if (pcck_buf->sq_rpt < 20)
  793. sq = 100;
  794. else
  795. sq = ((64-sq) * 100) / 44;
  796. }
  797. prframe->u.hdr.attrib.signal_qual = sq;
  798. prframe->u.hdr.attrib.rx_mimo_signal_qual[0] = sq;
  799. prframe->u.hdr.attrib.rx_mimo_signal_qual[1] = -1;
  800. } else {
  801. /* (1)Get RSSI for HT rate */
  802. for (i = 0; i < ((padapter->registrypriv.rf_config) &
  803. 0x0f) ; i++) {
  804. rf_rx_num++;
  805. rx_pwr[i] = ((pphy_head[PHY_STAT_GAIN_TRSW_SHT + i]
  806. & 0x3F) * 2) - 110;
  807. /* Translate DBM to percentage. */
  808. rssi = query_rx_pwr_percentage(rx_pwr[i]);
  809. total_rssi += rssi;
  810. }
  811. /* (2)PWDB, Average PWDB cacluated by hardware (for
  812. * rate adaptive) */
  813. rx_pwr_all = (((pphy_head[PHY_STAT_PWDB_ALL_SHT]) >> 1) & 0x7f)
  814. - 106;
  815. pwdb_all = query_rx_pwr_percentage(rx_pwr_all);
  816. {
  817. /* (3)EVM of HT rate */
  818. if (prframe->u.hdr.attrib.htc &&
  819. prframe->u.hdr.attrib.mcs_rate >= 20 &&
  820. prframe->u.hdr.attrib.mcs_rate <= 27) {
  821. /* both spatial stream make sense */
  822. max_spatial_stream = 2;
  823. } else {
  824. /* only spatial stream 1 makes sense */
  825. max_spatial_stream = 1;
  826. }
  827. for (i = 0; i < max_spatial_stream; i++) {
  828. evm = evm_db2percentage((pphy_head
  829. [PHY_STAT_RXEVM_SHT + i]));/*dbm*/
  830. prframe->u.hdr.attrib.signal_qual =
  831. (u8)(evm & 0xff);
  832. prframe->u.hdr.attrib.rx_mimo_signal_qual[i] =
  833. (u8)(evm & 0xff);
  834. }
  835. }
  836. }
  837. /* UI BSS List signal strength(in percentage), make it good looking,
  838. * from 0~100. It is assigned to the BSS List in
  839. * GetValueFromBeaconOrProbeRsp(). */
  840. if (bcck_rate)
  841. prframe->u.hdr.attrib.signal_strength =
  842. (u8)r8712_signal_scale_mapping(pwdb_all);
  843. else {
  844. if (rf_rx_num != 0)
  845. prframe->u.hdr.attrib.signal_strength =
  846. (u8)(r8712_signal_scale_mapping(total_rssi /=
  847. rf_rx_num));
  848. }
  849. }
  850. static void process_link_qual(struct _adapter *padapter,
  851. union recv_frame *prframe)
  852. {
  853. u32 last_evm = 0, tmpVal;
  854. struct rx_pkt_attrib *pattrib;
  855. if (prframe == NULL || padapter == NULL)
  856. return;
  857. pattrib = &prframe->u.hdr.attrib;
  858. if (pattrib->signal_qual != 0) {
  859. /*
  860. * 1. Record the general EVM to the sliding window.
  861. */
  862. if (padapter->recvpriv.signal_qual_data.total_num++ >=
  863. PHY_LINKQUALITY_SLID_WIN_MAX) {
  864. padapter->recvpriv.signal_qual_data.total_num =
  865. PHY_LINKQUALITY_SLID_WIN_MAX;
  866. last_evm = padapter->recvpriv.signal_qual_data.elements
  867. [padapter->recvpriv.signal_qual_data.index];
  868. padapter->recvpriv.signal_qual_data.total_val -=
  869. last_evm;
  870. }
  871. padapter->recvpriv.signal_qual_data.total_val +=
  872. pattrib->signal_qual;
  873. padapter->recvpriv.signal_qual_data.elements[padapter->
  874. recvpriv.signal_qual_data.index++] =
  875. pattrib->signal_qual;
  876. if (padapter->recvpriv.signal_qual_data.index >=
  877. PHY_LINKQUALITY_SLID_WIN_MAX)
  878. padapter->recvpriv.signal_qual_data.index = 0;
  879. /* <1> Showed on UI for user, in percentage. */
  880. tmpVal = padapter->recvpriv.signal_qual_data.total_val /
  881. padapter->recvpriv.signal_qual_data.total_num;
  882. padapter->recvpriv.signal = (u8)tmpVal;
  883. }
  884. }
  885. static void process_rssi(struct _adapter *padapter, union recv_frame *prframe)
  886. {
  887. u32 last_rssi, tmp_val;
  888. struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
  889. if (padapter->recvpriv.signal_strength_data.total_num++ >=
  890. PHY_RSSI_SLID_WIN_MAX) {
  891. padapter->recvpriv.signal_strength_data.total_num =
  892. PHY_RSSI_SLID_WIN_MAX;
  893. last_rssi = padapter->recvpriv.signal_strength_data.elements
  894. [padapter->recvpriv.signal_strength_data.index];
  895. padapter->recvpriv.signal_strength_data.total_val -= last_rssi;
  896. }
  897. padapter->recvpriv.signal_strength_data.total_val +=
  898. pattrib->signal_strength;
  899. padapter->recvpriv.signal_strength_data.elements[padapter->recvpriv.
  900. signal_strength_data.index++] =
  901. pattrib->signal_strength;
  902. if (padapter->recvpriv.signal_strength_data.index >=
  903. PHY_RSSI_SLID_WIN_MAX)
  904. padapter->recvpriv.signal_strength_data.index = 0;
  905. tmp_val = padapter->recvpriv.signal_strength_data.total_val /
  906. padapter->recvpriv.signal_strength_data.total_num;
  907. padapter->recvpriv.rssi = (s8)translate2dbm(padapter, (u8)tmp_val);
  908. }
  909. static void process_phy_info(struct _adapter *padapter,
  910. union recv_frame *prframe)
  911. {
  912. query_rx_phy_status(padapter, prframe);
  913. process_rssi(padapter, prframe);
  914. process_link_qual(padapter, prframe);
  915. }
  916. int recv_func(struct _adapter *padapter, void *pcontext)
  917. {
  918. struct rx_pkt_attrib *pattrib;
  919. union recv_frame *prframe, *orig_prframe;
  920. int retval = _SUCCESS;
  921. struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
  922. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  923. prframe = (union recv_frame *)pcontext;
  924. orig_prframe = prframe;
  925. pattrib = &prframe->u.hdr.attrib;
  926. if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)) {
  927. if (pattrib->crc_err == 1)
  928. padapter->mppriv.rx_crcerrpktcount++;
  929. else
  930. padapter->mppriv.rx_pktcount++;
  931. if (check_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE) == false) {
  932. /* free this recv_frame */
  933. r8712_free_recvframe(orig_prframe, pfree_recv_queue);
  934. goto _exit_recv_func;
  935. }
  936. }
  937. /* check the frame crtl field and decache */
  938. retval = r8712_validate_recv_frame(padapter, prframe);
  939. if (retval != _SUCCESS) {
  940. /* free this recv_frame */
  941. r8712_free_recvframe(orig_prframe, pfree_recv_queue);
  942. goto _exit_recv_func;
  943. }
  944. process_phy_info(padapter, prframe);
  945. prframe = r8712_decryptor(padapter, prframe);
  946. if (prframe == NULL) {
  947. retval = _FAIL;
  948. goto _exit_recv_func;
  949. }
  950. prframe = r8712_recvframe_chk_defrag(padapter, prframe);
  951. if (prframe == NULL)
  952. goto _exit_recv_func;
  953. prframe = r8712_portctrl(padapter, prframe);
  954. if (prframe == NULL) {
  955. retval = _FAIL;
  956. goto _exit_recv_func;
  957. }
  958. retval = r8712_process_recv_indicatepkts(padapter, prframe);
  959. if (retval != _SUCCESS) {
  960. r8712_free_recvframe(orig_prframe, pfree_recv_queue);
  961. goto _exit_recv_func;
  962. }
  963. _exit_recv_func:
  964. return retval;
  965. }
  966. static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb)
  967. {
  968. u8 *pbuf, shift_sz = 0;
  969. u8 frag, mf;
  970. uint pkt_len;
  971. u32 transfer_len;
  972. struct recv_stat *prxstat;
  973. u16 pkt_cnt, drvinfo_sz, pkt_offset, tmp_len, alloc_sz;
  974. struct __queue *pfree_recv_queue;
  975. _pkt *pkt_copy = NULL;
  976. union recv_frame *precvframe = NULL;
  977. struct recv_priv *precvpriv = &padapter->recvpriv;
  978. pfree_recv_queue = &(precvpriv->free_recv_queue);
  979. pbuf = pskb->data;
  980. prxstat = (struct recv_stat *)pbuf;
  981. pkt_cnt = (le32_to_cpu(prxstat->rxdw2)>>16)&0xff;
  982. pkt_len = le32_to_cpu(prxstat->rxdw0)&0x00003fff;
  983. transfer_len = pskb->len;
  984. /* Test throughput with Netgear 3700 (No security) with Chariot 3T3R
  985. * pairs. The packet count will be a big number so that the containing
  986. * packet will effect the Rx reordering. */
  987. if (transfer_len < pkt_len) {
  988. /* In this case, it means the MAX_RECVBUF_SZ is too small to
  989. * get the data from 8712u. */
  990. return _FAIL;
  991. }
  992. do {
  993. prxstat = (struct recv_stat *)pbuf;
  994. pkt_len = le32_to_cpu(prxstat->rxdw0)&0x00003fff;
  995. /* more fragment bit */
  996. mf = (le32_to_cpu(prxstat->rxdw1) >> 27) & 0x1;
  997. /* ragmentation number */
  998. frag = (le32_to_cpu(prxstat->rxdw2) >> 12) & 0xf;
  999. /* uint 2^3 = 8 bytes */
  1000. drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16;
  1001. drvinfo_sz = drvinfo_sz<<3;
  1002. if (pkt_len <= 0)
  1003. goto _exit_recvbuf2recvframe;
  1004. /* Qos data, wireless lan header length is 26 */
  1005. if ((le32_to_cpu(prxstat->rxdw0) >> 23) & 0x01)
  1006. shift_sz = 2;
  1007. precvframe = r8712_alloc_recvframe(pfree_recv_queue);
  1008. if (precvframe == NULL)
  1009. goto _exit_recvbuf2recvframe;
  1010. _init_listhead(&precvframe->u.hdr.list);
  1011. precvframe->u.hdr.precvbuf = NULL; /*can't access the precvbuf*/
  1012. precvframe->u.hdr.len = 0;
  1013. tmp_len = pkt_len + drvinfo_sz + RXDESC_SIZE;
  1014. pkt_offset = (u16)_RND128(tmp_len);
  1015. /* for first fragment packet, driver need allocate 1536 +
  1016. * drvinfo_sz + RXDESC_SIZE to defrag packet. */
  1017. if ((mf == 1) && (frag == 0))
  1018. alloc_sz = 1658;
  1019. else
  1020. alloc_sz = tmp_len;
  1021. /* 2 is for IP header 4 bytes alignment in QoS packet case.
  1022. * 4 is for skb->data 4 bytes alignment. */
  1023. alloc_sz += 6;
  1024. pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz);
  1025. if (pkt_copy) {
  1026. pkt_copy->dev = padapter->pnetdev;
  1027. precvframe->u.hdr.pkt = pkt_copy;
  1028. skb_reserve(pkt_copy, 4 - ((addr_t)(pkt_copy->data)
  1029. % 4));
  1030. skb_reserve(pkt_copy, shift_sz);
  1031. memcpy(pkt_copy->data, pbuf, tmp_len);
  1032. precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data =
  1033. precvframe->u.hdr.rx_tail = pkt_copy->data;
  1034. precvframe->u.hdr.rx_end = pkt_copy->data + alloc_sz;
  1035. } else {
  1036. precvframe->u.hdr.pkt = skb_clone(pskb, GFP_ATOMIC);
  1037. precvframe->u.hdr.rx_head = pbuf;
  1038. precvframe->u.hdr.rx_data = pbuf;
  1039. precvframe->u.hdr.rx_tail = pbuf;
  1040. precvframe->u.hdr.rx_end = pbuf + alloc_sz;
  1041. }
  1042. recvframe_put(precvframe, tmp_len);
  1043. recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE);
  1044. /* because the endian issue, driver avoid reference to the
  1045. * rxstat after calling update_recvframe_attrib_from_recvstat();
  1046. */
  1047. update_recvframe_attrib_from_recvstat(&precvframe->u.hdr.attrib,
  1048. prxstat);
  1049. r8712_recv_entry(precvframe);
  1050. transfer_len -= pkt_offset;
  1051. pbuf += pkt_offset;
  1052. pkt_cnt--;
  1053. precvframe = NULL;
  1054. pkt_copy = NULL;
  1055. } while ((transfer_len > 0) && pkt_cnt > 0);
  1056. _exit_recvbuf2recvframe:
  1057. return _SUCCESS;
  1058. }
  1059. static void recv_tasklet(void *priv)
  1060. {
  1061. struct sk_buff *pskb;
  1062. struct _adapter *padapter = (struct _adapter *)priv;
  1063. struct recv_priv *precvpriv = &padapter->recvpriv;
  1064. while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
  1065. recvbuf2recvframe(padapter, pskb);
  1066. skb_reset_tail_pointer(pskb);
  1067. pskb->len = 0;
  1068. skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
  1069. }
  1070. }