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