xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/rtl8188e/sdio/rtl8189es_recv.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _RTL8189ES_RECV_C_
21 
22 #include <drv_conf.h>
23 
24 #if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS)
25 #error "Shall be Linux or Windows, but not both!\n"
26 #endif
27 
28 #include <drv_types.h>
29 #include <recv_osdep.h>
30 #include <rtl8188e_hal.h>
31 
32 static void rtl8188es_recv_tasklet(void *priv);
33 
initrecvbuf(struct recv_buf * precvbuf,PADAPTER padapter)34 static s32 initrecvbuf(struct recv_buf *precvbuf, PADAPTER padapter)
35 {
36 	_rtw_init_listhead(&precvbuf->list);
37 	_rtw_spinlock_init(&precvbuf->recvbuf_lock);
38 
39 	precvbuf->adapter = padapter;
40 
41 	return _SUCCESS;
42 }
43 
freerecvbuf(struct recv_buf * precvbuf)44 static void freerecvbuf(struct recv_buf *precvbuf)
45 {
46 	_rtw_spinlock_free(&precvbuf->recvbuf_lock);
47 }
48 
49 /*
50  * Initialize recv private variable for hardware dependent
51  * 1. recv buf
52  * 2. recv tasklet
53  *
54  */
rtl8188es_init_recv_priv(PADAPTER padapter)55 s32 rtl8188es_init_recv_priv(PADAPTER padapter)
56 {
57 	s32			res;
58 	u32			i, n;
59 	u32 max_recvbuf_sz = 0;
60 	struct recv_priv	*precvpriv;
61 	struct recv_buf		*precvbuf;
62 
63 
64 	res = _SUCCESS;
65 	precvpriv = &padapter->recvpriv;
66 
67 	//3 1. init recv buffer
68 	_rtw_init_queue(&precvpriv->free_recv_buf_queue);
69 	_rtw_init_queue(&precvpriv->recv_buf_pending_queue);
70 
71 	n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
72 	precvpriv->pallocated_recv_buf = rtw_zmalloc(n);
73 	if (precvpriv->pallocated_recv_buf == NULL) {
74 		res = _FAIL;
75 		RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("alloc recv_buf fail!\n"));
76 		goto exit;
77 	}
78 
79 	precvpriv->precv_buf = (u8*)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4);
80 
81 	// init each recv buffer
82 	precvbuf = (struct recv_buf*)precvpriv->precv_buf;
83 	for (i = 0; i < NR_RECVBUFF; i++)
84 	{
85 		res = initrecvbuf(precvbuf, padapter);
86 		if (res == _FAIL)
87 			break;
88 
89 		res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
90 		if (res == _FAIL) {
91 			freerecvbuf(precvbuf);
92 			break;
93 		}
94 
95 #ifdef CONFIG_SDIO_RX_COPY
96 		if (precvbuf->pskb == NULL) {
97 			SIZE_PTR tmpaddr=0;
98 			SIZE_PTR alignment=0;
99 
100 			rtw_hal_get_def_var(padapter, HAL_DEF_MAX_RECVBUF_SZ,
101 					    &max_recvbuf_sz);
102 
103 			if (max_recvbuf_sz == 0)
104 				max_recvbuf_sz = MAX_RECVBUF_SZ;
105 
106 			precvbuf->pskb = rtw_skb_alloc(max_recvbuf_sz +
107 						       RECVBUFF_ALIGN_SZ);
108 
109 			if(precvbuf->pskb)
110 			{
111 				precvbuf->pskb->dev = padapter->pnetdev;
112 
113 				tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
114 				alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
115 				skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
116 
117 				precvbuf->phead = precvbuf->pskb->head;
118 				precvbuf->pdata = precvbuf->pskb->data;
119 				precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
120 				precvbuf->pend = skb_end_pointer(precvbuf->pskb);
121 				precvbuf->len = 0;
122 			}
123 
124 			if (precvbuf->pskb == NULL) {
125 				DBG_871X("%s: alloc_skb fail!\n", __FUNCTION__);
126 			}
127 		}
128 #endif
129 
130 		rtw_list_insert_tail(&precvbuf->list, &precvpriv->free_recv_buf_queue.queue);
131 
132 		precvbuf++;
133 	}
134 	precvpriv->free_recv_buf_queue_cnt = i;
135 
136 	if (res == _FAIL)
137 		goto initbuferror;
138 
139 	//3 2. init tasklet
140 #ifdef PLATFORM_LINUX
141 	tasklet_init(&precvpriv->recv_tasklet,
142 	     (void(*)(unsigned long))rtl8188es_recv_tasklet,
143 	     (unsigned long)padapter);
144 #endif
145 
146 	goto exit;
147 
148 initbuferror:
149 	precvbuf = (struct recv_buf*)precvpriv->precv_buf;
150 	if (precvbuf) {
151 		n = precvpriv->free_recv_buf_queue_cnt;
152 		precvpriv->free_recv_buf_queue_cnt = 0;
153 		for (i = 0; i < n ; i++)
154 		{
155 			rtw_list_delete(&precvbuf->list);
156 			rtw_os_recvbuf_resource_free(padapter, precvbuf);
157 			freerecvbuf(precvbuf);
158 			precvbuf++;
159 		}
160 		precvpriv->precv_buf = NULL;
161 	}
162 
163 	if (precvpriv->pallocated_recv_buf) {
164 		n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
165 		rtw_mfree(precvpriv->pallocated_recv_buf, n);
166 		precvpriv->pallocated_recv_buf = NULL;
167 	}
168 
169 exit:
170 	return res;
171 }
172 
173 /*
174  * Free recv private variable of hardware dependent
175  * 1. recv buf
176  * 2. recv tasklet
177  *
178  */
rtl8188es_free_recv_priv(PADAPTER padapter)179 void rtl8188es_free_recv_priv(PADAPTER padapter)
180 {
181 	u32			i, n;
182 	struct recv_priv	*precvpriv;
183 	struct recv_buf		*precvbuf;
184 
185 
186 	precvpriv = &padapter->recvpriv;
187 
188 	//3 1. kill tasklet
189 #ifdef PLATFORM_LINUX
190 	tasklet_kill(&precvpriv->recv_tasklet);
191 #endif
192 
193 	//3 2. free all recv buffers
194 	precvbuf = (struct recv_buf*)precvpriv->precv_buf;
195 	if (precvbuf) {
196 		n = NR_RECVBUFF;
197 		precvpriv->free_recv_buf_queue_cnt = 0;
198 		for (i = 0; i < n ; i++)
199 		{
200 			rtw_list_delete(&precvbuf->list);
201 			rtw_os_recvbuf_resource_free(padapter, precvbuf);
202 			freerecvbuf(precvbuf);
203 			precvbuf++;
204 		}
205 		precvpriv->precv_buf = NULL;
206 	}
207 
208 	if (precvpriv->pallocated_recv_buf) {
209 		n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
210 		rtw_mfree(precvpriv->pallocated_recv_buf, n);
211 		precvpriv->pallocated_recv_buf = NULL;
212 	}
213 }
214 
215 #ifdef CONFIG_SDIO_RX_COPY
pre_recv_entry(union recv_frame * precvframe,struct recv_buf * precvbuf,u8 * pphy_status)216 static s32 pre_recv_entry(union recv_frame *precvframe, struct recv_buf	*precvbuf, u8 *pphy_status)
217 {
218 	s32 ret=_SUCCESS;
219 #ifdef CONFIG_CONCURRENT_MODE
220 	u8 *secondary_myid, *paddr1;
221 	union recv_frame	*precvframe_if2 = NULL;
222 	_adapter *primary_padapter = precvframe->u.hdr.adapter;
223 	_adapter *secondary_padapter = primary_padapter->pbuddy_adapter;
224 	struct recv_priv *precvpriv = &primary_padapter->recvpriv;
225 	_queue *pfree_recv_queue = &precvpriv->free_recv_queue;
226 	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(primary_padapter);
227 
228 	if(!secondary_padapter)
229 		return ret;
230 
231 	paddr1 = GetAddr1Ptr(precvframe->u.hdr.rx_data);
232 
233 	if(IS_MCAST(paddr1) == _FALSE)//unicast packets
234 	{
235 		secondary_myid = adapter_mac_addr(secondary_padapter);
236 
237 		if(_rtw_memcmp(paddr1, secondary_myid, ETH_ALEN))
238 		{
239 			//change to secondary interface
240 			precvframe->u.hdr.adapter = secondary_padapter;
241 		}
242 
243 		//ret = recv_entry(precvframe);
244 
245 	}
246 	else // Handle BC/MC Packets
247 	{
248 		//clone/copy to if2
249 		_pkt	 *pkt_copy = NULL;
250 		struct rx_pkt_attrib *pattrib = NULL;
251 
252 		precvframe_if2 = rtw_alloc_recvframe(pfree_recv_queue);
253 
254 		if(!precvframe_if2)
255 			return _FAIL;
256 
257 		precvframe_if2->u.hdr.adapter = secondary_padapter;
258 		_rtw_memcpy(&precvframe_if2->u.hdr.attrib, &precvframe->u.hdr.attrib, sizeof(struct rx_pkt_attrib));
259 		pattrib = &precvframe_if2->u.hdr.attrib;
260 
261 		//driver need to set skb len for skb_copy().
262 		//If skb->len is zero, skb_copy() will not copy data from original skb.
263 		skb_put(precvframe->u.hdr.pkt, pattrib->pkt_len);
264 
265 		pkt_copy = rtw_skb_copy( precvframe->u.hdr.pkt);
266 		if (pkt_copy == NULL)
267 		{
268 			if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0))
269 			{
270 				DBG_8192C("pre_recv_entry(): rtw_skb_copy fail , drop frag frame \n");
271 				rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
272 				return ret;
273 			}
274 
275 			pkt_copy = rtw_skb_clone( precvframe->u.hdr.pkt);
276 			if(pkt_copy == NULL)
277 			{
278 				DBG_8192C("pre_recv_entry(): rtw_skb_clone fail , drop frame\n");
279 				rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
280 				return ret;
281 			}
282 		}
283 
284 		pkt_copy->dev = secondary_padapter->pnetdev;
285 
286 		precvframe_if2->u.hdr.pkt = pkt_copy;
287 		precvframe_if2->u.hdr.rx_head = pkt_copy->head;
288 		precvframe_if2->u.hdr.rx_data = pkt_copy->data;
289 		precvframe_if2->u.hdr.rx_tail = skb_tail_pointer(pkt_copy);
290 		precvframe_if2->u.hdr.rx_end = skb_end_pointer(pkt_copy);
291 		precvframe_if2->u.hdr.len = pkt_copy->len;
292 
293 		//recvframe_put(precvframe_if2, pattrib->pkt_len);
294 
295 		if ( pHalData->ReceiveConfig & RCR_APPFCS)
296 			recvframe_pull_tail(precvframe_if2, IEEE80211_FCS_LEN);
297 
298 		if (pattrib->physt)
299 			rx_query_phy_status(precvframe_if2, pphy_status);
300 
301 		if(rtw_recv_entry(precvframe_if2) != _SUCCESS)
302 		{
303 			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
304 				("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n"));
305 		}
306 	}
307 
308 	if (precvframe->u.hdr.attrib.physt)
309 		rx_query_phy_status(precvframe, pphy_status);
310 	ret = rtw_recv_entry(precvframe);
311 
312 #endif
313 
314 	return ret;
315 
316 }
317 
rtl8188es_recv_tasklet(void * priv)318 static void rtl8188es_recv_tasklet(void *priv)
319 {
320 	PADAPTER			padapter;
321 	PHAL_DATA_TYPE		pHalData;
322 	struct recv_priv		*precvpriv;
323 	struct recv_buf		*precvbuf;
324 	union recv_frame		*precvframe;
325 	struct recv_frame_hdr	*phdr;
326 	struct rx_pkt_attrib	*pattrib;
327 	_irqL	irql;
328 	u8		*ptr;
329 	u32		pkt_offset, skb_len, alloc_sz;
330 	s32		transfer_len;
331 	_pkt		*pkt_copy = NULL;
332 	u8 *pphy_status = NULL;
333 	u8		shift_sz = 0, rx_report_sz = 0;
334 
335 
336 	padapter = (PADAPTER)priv;
337 	pHalData = GET_HAL_DATA(padapter);
338 	precvpriv = &padapter->recvpriv;
339 
340 	do {
341 		if (RTW_CANNOT_RUN(padapter)) {
342 			DBG_8192C("recv_tasklet => bDriverStopped or bSurpriseRemoved\n");
343 			break;
344 		}
345 
346 		precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
347 		if (NULL == precvbuf) break;
348 
349 		transfer_len = (s32)precvbuf->len;
350 		ptr = precvbuf->pdata;
351 
352 		do {
353 			precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
354 			if (precvframe == NULL) {
355 				RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: no enough recv frame!\n",__FUNCTION__));
356 				rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
357 
358 				// The case of can't allocte recvframe should be temporary,
359 				// schedule again and hope recvframe is available next time.
360 #ifdef PLATFORM_LINUX
361 				tasklet_schedule(&precvpriv->recv_tasklet);
362 #endif
363 				return;
364 			}
365 
366 			//rx desc parsing
367 			rtl8188e_query_rx_desc_status(precvframe, (struct recv_stat*)ptr);
368 
369 			pattrib = &precvframe->u.hdr.attrib;
370 
371 			// fix Hardware RX data error, drop whole recv_buffer
372 			if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err)
373 			{
374 				#if !(MP_DRIVER==1)
375 				DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
376 				#endif
377 				rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
378 				break;
379 			}
380 
381 			if (pHalData->ReceiveConfig & RCR_APP_BA_SSN)
382 				rx_report_sz = RXDESC_SIZE + 4 + pattrib->drvinfo_sz;
383 			else
384 				rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz;
385 
386 			pkt_offset = rx_report_sz + pattrib->shift_sz + pattrib->pkt_len;
387 
388 			if ((pattrib->pkt_len==0) || (pkt_offset>transfer_len)) {
389 				DBG_8192C("%s()-%d: RX Warning!,pkt_len==0 or pkt_offset(%d)> transfoer_len(%d) \n", __FUNCTION__, __LINE__, pkt_offset, transfer_len);
390 				rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
391 				break;
392 			}
393 
394 			if ((pattrib->crc_err) || (pattrib->icv_err))
395 			{
396 			#ifdef CONFIG_MP_INCLUDED
397 				if (padapter->registrypriv.mp_mode == 1)
398 				{
399 					if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0))
400 					{
401 						if (pattrib->crc_err == 1)
402 							padapter->mppriv.rx_crcerrpktcount++;
403 					}
404 				}
405 			#endif
406 
407 				DBG_8192C("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err);
408 				rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
409 			}
410 			else
411 			{
412 				//	Modified by Albert 20101213
413 				//	For 8 bytes IP header alignment.
414 				if (pattrib->qos)	//	Qos data, wireless lan header length is 26
415 				{
416 					shift_sz = 6;
417 				}
418 				else
419 				{
420 					shift_sz = 0;
421 				}
422 
423 				skb_len = pattrib->pkt_len;
424 
425 				// for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet.
426 				// modify alloc_sz for recvive crc error packet by thomas 2011-06-02
427 				if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)){
428 					//alloc_sz = 1664;	//1664 is 128 alignment.
429 					if(skb_len <= 1650)
430 						alloc_sz = 1664;
431 					else
432 						alloc_sz = skb_len + 14;
433 				}
434 				else {
435 					alloc_sz = skb_len;
436 					//	6 is for IP header 8 bytes alignment in QoS packet case.
437 					//	8 is for skb->data 4 bytes alignment.
438 					alloc_sz += 14;
439 				}
440 
441 				pkt_copy = rtw_skb_alloc(alloc_sz);
442 
443 				if(pkt_copy)
444 				{
445 					pkt_copy->dev = padapter->pnetdev;
446 					precvframe->u.hdr.pkt = pkt_copy;
447 					skb_reserve( pkt_copy, 8 - ((SIZE_PTR)( pkt_copy->data ) & 7 ));//force pkt_copy->data at 8-byte alignment address
448 					skb_reserve( pkt_copy, shift_sz );//force ip_hdr at 8-byte alignment address according to shift_sz.
449 					_rtw_memcpy(pkt_copy->data, (ptr + rx_report_sz + pattrib->shift_sz), skb_len);
450 					precvframe->u.hdr.rx_head = pkt_copy->head;
451 					precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_copy->data;
452 					precvframe->u.hdr.rx_end = skb_end_pointer(pkt_copy);
453 				}
454 				else
455 				{
456 					if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0))
457 					{
458 						DBG_8192C("rtl8188es_recv_tasklet: alloc_skb fail , drop frag frame \n");
459 						rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
460 						break;
461 					}
462 
463 					precvframe->u.hdr.pkt = rtw_skb_clone(precvbuf->pskb);
464 					if(precvframe->u.hdr.pkt)
465 					{
466 						_pkt	*pkt_clone = precvframe->u.hdr.pkt;
467 
468 						pkt_clone->data = ptr + rx_report_sz + pattrib->shift_sz;
469 						skb_reset_tail_pointer(pkt_clone);
470 						precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail
471 							= pkt_clone->data;
472 						precvframe->u.hdr.rx_end =  pkt_clone->data + skb_len;
473 					}
474 					else
475 					{
476 						DBG_8192C("rtl8188es_recv_tasklet: rtw_skb_clone fail\n");
477 						rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
478 						break;
479 					}
480 				}
481 
482 				recvframe_put(precvframe, skb_len);
483 				//recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE);
484 
485 				if (pHalData->ReceiveConfig & RCR_APPFCS) {
486 					recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
487 					pattrib->pkt_len -= IEEE80211_FCS_LEN;
488 				}
489 
490 				// update drv info
491 				if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
492 					//rtl8723s_update_bassn(padapter, (ptr + RXDESC_SIZE));
493 				}
494 
495 				if(pattrib->pkt_rpt_type == NORMAL_RX)//Normal rx packet
496 				{
497 					pphy_status = (ptr + (rx_report_sz - pattrib->drvinfo_sz));
498 
499 #ifdef CONFIG_CONCURRENT_MODE
500 					if(rtw_buddy_adapter_up(padapter))
501 					{
502 						if(pre_recv_entry(precvframe, precvbuf, pphy_status) != _SUCCESS)
503 						{
504 							RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
505 								("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n"));
506 						}
507 					}
508 					else
509 #endif
510 					{
511 						if (pattrib->physt)
512 							rx_query_phy_status(precvframe, pphy_status);
513 
514 						if (rtw_recv_entry(precvframe) != _SUCCESS)
515 						{
516 							RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n",__FUNCTION__));
517 						}
518 					}
519 				}
520 				else{ // pkt_rpt_type == TX_REPORT1-CCX, TX_REPORT2-TX RTP,HIS_REPORT-USB HISR RTP
521 
522 					//enqueue recvframe to txrtp queue
523 					if(pattrib->pkt_rpt_type == TX_REPORT1){
524 						//DBG_8192C("rx CCX \n");
525 						//CCX-TXRPT ack for xmit mgmt frames.
526 						handle_txrpt_ccx_88e(padapter, precvframe->u.hdr.rx_data);
527 					}
528 					else if(pattrib->pkt_rpt_type == TX_REPORT2){
529 						//printk("rx TX RPT \n");
530 						ODM_RA_TxRPT2Handle_8188E(
531 									&pHalData->odmpriv,
532 									precvframe->u.hdr.rx_data,
533 									pattrib->pkt_len,
534 									pattrib->MacIDValidEntry[0],
535 									pattrib->MacIDValidEntry[1]
536 									);
537 
538 					}
539 					/*
540 					else if(pattrib->pkt_rpt_type == HIS_REPORT){
541 						printk("rx USB HISR \n");
542 					}*/
543 
544 					rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
545 
546 				}
547 			}
548 
549 			// Page size of receive package is 128 bytes alignment =>DMA AGG
550 
551 			pkt_offset = _RND128(pkt_offset);
552 			transfer_len -= pkt_offset;
553 			ptr += pkt_offset;
554 			precvframe = NULL;
555 			pkt_copy = NULL;
556 		}while(transfer_len>0);
557 
558 		precvbuf->len = 0;
559 
560 		rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
561 	} while (1);
562 
563 }
564 #else
pre_recv_entry(union recv_frame * precvframe,struct recv_buf * precvbuf,u8 * pphy_status)565 static s32 pre_recv_entry(union recv_frame *precvframe, struct recv_buf	*precvbuf, u8 *pphy_status)
566 {
567 	s32 ret=_SUCCESS;
568 #ifdef CONFIG_CONCURRENT_MODE
569 	u8 *secondary_myid, *paddr1;
570 	union recv_frame	*precvframe_if2 = NULL;
571 	_adapter *primary_padapter = precvframe->u.hdr.adapter;
572 	_adapter *secondary_padapter = primary_padapter->pbuddy_adapter;
573 	struct recv_priv *precvpriv = &primary_padapter->recvpriv;
574 	_queue *pfree_recv_queue = &precvpriv->free_recv_queue;
575 	u8	*pbuf = precvframe->u.hdr.rx_data;
576 	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(primary_padapter);
577 
578 	if(!secondary_padapter)
579 		return ret;
580 
581 	paddr1 = GetAddr1Ptr(pbuf);
582 
583 	if(IS_MCAST(paddr1) == _FALSE)//unicast packets
584 	{
585 		secondary_myid = adapter_mac_addr(secondary_padapter);
586 
587 		if(_rtw_memcmp(paddr1, secondary_myid, ETH_ALEN))
588 		{
589 			//change to secondary interface
590 			precvframe->u.hdr.adapter = secondary_padapter;
591 		}
592 
593 		//ret = recv_entry(precvframe);
594 
595 	}
596 	else // Handle BC/MC Packets
597 	{
598 		//clone/copy to if2
599 		u8 shift_sz = 0;
600 		u32 alloc_sz, skb_len;
601 		_pkt	 *pkt_copy = NULL;
602 		struct rx_pkt_attrib *pattrib = NULL;
603 
604 		precvframe_if2 = rtw_alloc_recvframe(pfree_recv_queue);
605 
606 		if(!precvframe_if2)
607 			return _FAIL;
608 
609 		precvframe_if2->u.hdr.adapter = secondary_padapter;
610 		_rtw_init_listhead(&precvframe_if2->u.hdr.list);
611 		precvframe_if2->u.hdr.precvbuf = NULL;	//can't access the precvbuf for new arch.
612 		precvframe_if2->u.hdr.len=0;
613 		_rtw_memcpy(&precvframe_if2->u.hdr.attrib, &precvframe->u.hdr.attrib, sizeof(struct rx_pkt_attrib));
614 		pattrib = &precvframe_if2->u.hdr.attrib;
615 
616 		pkt_copy = rtw_skb_copy( precvframe->u.hdr.pkt);
617 		if (pkt_copy == NULL)
618 		{
619 			RT_TRACE(_module_rtl871x_recv_c_, _drv_crit_, ("%s: no enough memory to allocate SKB!\n",__FUNCTION__));
620 			rtw_free_recvframe(precvframe_if2, &precvpriv->free_recv_queue);
621 			rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
622 
623 			// The case of can't allocte skb is serious and may never be recovered,
624 			// once bDriverStopped is enable, this task should be stopped.
625 			if (!rtw_is_drv_stopped(secondary_padapter))
626 #ifdef PLATFORM_LINUX
627 				tasklet_schedule(&precvpriv->recv_tasklet);
628 #endif
629 			return ret;
630 		}
631 		pkt_copy->dev = secondary_padapter->pnetdev;
632 
633 
634 
635 		if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)){
636 			//alloc_sz = 1664;	//1664 is 128 alignment.
637 			if(skb_len <= 1650)
638 				alloc_sz = 1664;
639 			else
640 				alloc_sz = skb_len + 14;
641 		}
642 		else {
643 			alloc_sz = skb_len;
644 			//	6 is for IP header 8 bytes alignment in QoS packet case.
645 			//	8 is for skb->data 4 bytes alignment.
646 			alloc_sz += 14;
647 		}
648 
649 #if 1
650 		precvframe_if2->u.hdr.pkt = pkt_copy;
651 		precvframe_if2->u.hdr.rx_head = pkt_copy->head;
652 		precvframe_if2->u.hdr.rx_data = precvframe_if2->u.hdr.rx_tail = pkt_copy->data;
653 		precvframe_if2->u.hdr.rx_end = pkt_copy->data + alloc_sz;
654 #endif
655 		recvframe_put(precvframe_if2, pkt_offset);
656 		recvframe_pull(precvframe_if2, RXDESC_SIZE + pattrib->drvinfo_sz);
657 
658 		if ( pHalData->ReceiveConfig & RCR_APPFCS)
659 			recvframe_pull_tail(precvframe_if2, IEEE80211_FCS_LEN);
660 
661 		if (pattrib->physt)
662 			rx_query_phy_status(precvframe_if2, pphy_status);
663 
664 		if(rtw_recv_entry(precvframe_if2) != _SUCCESS)
665 		{
666 			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
667 				("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n"));
668 		}
669 	}
670 
671 	if (precvframe->u.hdr.attrib.physt)
672 		rx_query_phy_status(precvframe, pphy_status);
673 	ret = rtw_recv_entry(precvframe);
674 
675 #endif
676 
677 	return ret;
678 
679 }
680 
rtl8188es_recv_tasklet(void * priv)681 static void rtl8188es_recv_tasklet(void *priv)
682 {
683 	PADAPTER				padapter;
684 	PHAL_DATA_TYPE			pHalData;
685 	struct recv_priv		*precvpriv;
686 	struct recv_buf			*precvbuf;
687 	union recv_frame		*precvframe;
688 	struct recv_frame_hdr	*phdr;
689 	struct rx_pkt_attrib	*pattrib;
690 	u8			*ptr;
691 	_pkt		*ppkt;
692 	u32			pkt_offset;
693 	_irqL		irql;
694 #ifdef CONFIG_CONCURRENT_MODE
695 	struct recv_stat	*prxstat;
696 #endif
697 
698 	padapter = (PADAPTER)priv;
699 	pHalData = GET_HAL_DATA(padapter);
700 	precvpriv = &padapter->recvpriv;
701 
702 	do {
703 		precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
704 		if (NULL == precvbuf) break;
705 
706 		ptr = precvbuf->pdata;
707 
708 		while (ptr < precvbuf->ptail)
709 		{
710 			precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
711 			if (precvframe == NULL) {
712 				RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: no enough recv frame!\n",__FUNCTION__));
713 				rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
714 
715 				// The case of can't allocte recvframe should be temporary,
716 				// schedule again and hope recvframe is available next time.
717 #ifdef PLATFORM_LINUX
718 				tasklet_schedule(&precvpriv->recv_tasklet);
719 #endif
720 				return;
721 			}
722 
723 			phdr = &precvframe->u.hdr;
724 			pattrib = &phdr->attrib;
725 
726 			//rx desc parsing
727 			rtl8188e_query_rx_desc_status(precvframe, (struct recv_stat*)ptr);
728 #ifdef CONFIG_CONCURRENT_MODE
729 			prxstat = (struct recv_stat*)ptr;
730 #endif
731 			// fix Hardware RX data error, drop whole recv_buffer
732 			if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err)
733 			{
734 				//#if !(MP_DRIVER==1)
735 				if (padapter->registrypriv.mp_mode == 0)
736 				DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
737 				//#endif
738 				rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
739 				break;
740 			}
741 
742 			pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->pkt_len;
743 
744 			if ((ptr + pkt_offset) > precvbuf->ptail) {
745 				DBG_8192C("%s()-%d: : next pkt len(%p,%d) exceed ptail(%p)!\n", __FUNCTION__, __LINE__, ptr, pkt_offset, precvbuf->ptail);
746 				rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
747 				break;
748 			}
749 
750 			if ((pattrib->crc_err) || (pattrib->icv_err))
751 			{
752 			#ifdef CONFIG_MP_INCLUDED
753 				if (padapter->registrypriv.mp_mode == 1)
754 				{
755 					if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0))
756 					{
757 						if (pattrib->crc_err == 1)
758 							padapter->mppriv.rx_crcerrpktcount++;
759 					}
760 				}
761 			#endif
762 
763 				DBG_8192C("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err);
764 				rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
765 			}
766 			else
767 			{
768 				ppkt = rtw_skb_clone(precvbuf->pskb);
769 				if (ppkt == NULL)
770 				{
771 					RT_TRACE(_module_rtl871x_recv_c_, _drv_crit_, ("%s: no enough memory to allocate SKB!\n",__FUNCTION__));
772 					rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
773 					rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
774 
775 					// The case of can't allocte skb is serious and may never be recovered,
776 					// once bDriverStopped is enable, this task should be stopped.
777 					if (!rtw_is_drv_stopped(padapter)) {
778 #ifdef PLATFORM_LINUX
779 						tasklet_schedule(&precvpriv->recv_tasklet);
780 #endif
781 					}
782 
783 					return;
784 				}
785 
786 				phdr->pkt = ppkt;
787 				phdr->len = 0;
788 				phdr->rx_head = precvbuf->phead;
789 				phdr->rx_data = phdr->rx_tail = precvbuf->pdata;
790 				phdr->rx_end = precvbuf->pend;
791 
792 				recvframe_put(precvframe, pkt_offset);
793 				recvframe_pull(precvframe, RXDESC_SIZE + pattrib->drvinfo_sz);
794 
795 				if (pHalData->ReceiveConfig & RCR_APPFCS)
796 					recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
797 
798 				// move to drv info position
799 				ptr += RXDESC_SIZE;
800 
801 				// update drv info
802 				if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
803 //					rtl8723s_update_bassn(padapter, pdrvinfo);
804 					ptr += 4;
805 				}
806 
807 				if(pattrib->pkt_rpt_type == NORMAL_RX)//Normal rx packet
808 				{
809 #ifdef CONFIG_CONCURRENT_MODE
810 					if(rtw_buddy_adapter_up(padapter))
811 					{
812 						if(pre_recv_entry(precvframe, precvbuf, ptr) != _SUCCESS)
813 						{
814 							RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
815 								("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n"));
816 						}
817 					}
818 					else
819 #endif
820 					{
821 						if (pattrib->physt)
822 							rx_query_phy_status(precvframe, ptr);
823 
824 					if (rtw_recv_entry(precvframe) != _SUCCESS)
825 					{
826 							RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
827 								("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n"));
828 						}
829 					}
830 				}
831 				else{ // pkt_rpt_type == TX_REPORT1-CCX, TX_REPORT2-TX RTP,HIS_REPORT-USB HISR RTP
832 
833 					//enqueue recvframe to txrtp queue
834 					if(pattrib->pkt_rpt_type == TX_REPORT1){
835 						DBG_8192C("rx CCX \n");
836 					}
837 					else if(pattrib->pkt_rpt_type == TX_REPORT2){
838 						//DBG_8192C("rx TX RPT \n");
839 						ODM_RA_TxRPT2Handle_8188E(
840 									&pHalData->odmpriv,
841 									precvframe->u.hdr.rx_data,
842 									pattrib->pkt_len,
843 									pattrib->MacIDValidEntry[0],
844 									pattrib->MacIDValidEntry[1]
845 									);
846 
847 					}
848 					/*
849 					else if(pattrib->pkt_rpt_type == HIS_REPORT){
850 						DBG_8192C("rx USB HISR \n");
851 					}*/
852 
853 					rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
854 
855 				}
856 			}
857 
858 			// Page size of receive package is 128 bytes alignment =>DMA AGG
859 
860 			pkt_offset = _RND128(pkt_offset);
861 			precvbuf->pdata += pkt_offset;
862 			ptr = precvbuf->pdata;
863 
864 		}
865 
866 		rtw_skb_free(precvbuf->pskb);
867 		precvbuf->pskb = NULL;
868 		rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
869 
870 	} while (1);
871 
872 }
873 #endif
874 
875