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