rtl8712_recv.c 34 KB

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