8723BU: Update 8723BU wifi driver to version v4.3.16_14189.20150519_BTCOEX2015119...
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723au / hal / rtl8723a / sdio / rtl8723as_recv.c
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 _RTL8723AS_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 <rtl8723a_hal.h>
31
32
33
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
44 static void freerecvbuf(struct recv_buf *precvbuf)
45 {
46         _rtw_spinlock_free(&precvbuf->recvbuf_lock);
47 }
48
49 static void update_recvframe_attrib(
50         union recv_frame *precvframe,
51         struct recv_stat *prxstat)
52 {
53         struct rx_pkt_attrib    *pattrib;
54         struct recv_stat        report;
55         PRXREPORT               prxreport;
56
57
58         report.rxdw0 = le32_to_cpu(prxstat->rxdw0);
59         report.rxdw1 = le32_to_cpu(prxstat->rxdw1);
60         report.rxdw2 = le32_to_cpu(prxstat->rxdw2);
61         report.rxdw3 = le32_to_cpu(prxstat->rxdw3);
62         report.rxdw4 = le32_to_cpu(prxstat->rxdw4);
63         report.rxdw5 = le32_to_cpu(prxstat->rxdw5);
64
65         prxreport = (PRXREPORT)&report;
66
67         pattrib = &precvframe->u.hdr.attrib;
68         _rtw_memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
69
70         // update rx report to recv_frame attribute
71         pattrib->pkt_len = (u16)prxreport->pktlen;
72         pattrib->drvinfo_sz = (u8)(prxreport->drvinfosize << 3);
73         pattrib->physt = (u8)prxreport->physt;
74
75         pattrib->crc_err = (u8)prxreport->crc32;
76         pattrib->icv_err = (u8)prxreport->icverr;
77
78         pattrib->bdecrypted = (u8)(prxreport->swdec ? 0 : 1);
79         pattrib->encrypt = (u8)prxreport->security;
80
81         pattrib->qos = (u8)prxreport->qos;
82         pattrib->priority = (u8)prxreport->tid;
83
84         pattrib->amsdu = (u8)prxreport->amsdu;
85
86         pattrib->seq_num = (u16)prxreport->seq;
87         pattrib->frag_num = (u8)prxreport->frag;
88         pattrib->mfrag = (u8)prxreport->mf;
89         pattrib->mdata = (u8)prxreport->md;
90
91         pattrib->mcs_rate = (u8)prxreport->rxmcs;
92         pattrib->rxht = (u8)prxreport->rxht;
93 }
94
95 /*
96  * Notice:
97  *      Before calling this function,
98  *      precvframe->u.hdr.rx_data should be ready!
99  */
100 void update_recvframe_phyinfo(
101         union recv_frame        *precvframe,
102         struct phy_stat *pphy_status)
103 {
104         PADAPTER                        padapter= precvframe->u.hdr.adapter;
105         struct rx_pkt_attrib    *pattrib = &precvframe->u.hdr.attrib;
106         HAL_DATA_TYPE           *pHalData = GET_HAL_DATA(padapter);     
107         PODM_PHY_INFO_T         pPHYInfo = (PODM_PHY_INFO_T)(&pattrib->phy_info);
108         
109         u8                      *wlanhdr;
110         ODM_PACKET_INFO_T       pkt_info;
111         u8 *sa;
112         //_irqL         irqL;
113         struct sta_priv *pstapriv;
114         struct sta_info *psta;
115         
116         pkt_info.bPacketMatchBSSID =_FALSE;
117         pkt_info.bPacketToSelf = _FALSE;
118         pkt_info.bPacketBeacon = _FALSE;
119
120
121         wlanhdr = get_recvframe_data(precvframe);
122
123         pkt_info.bPacketMatchBSSID = ((!IsFrameTypeCtrl(wlanhdr)) &&
124                 !pattrib->icv_err && !pattrib->crc_err &&
125                 _rtw_memcmp(get_hdr_bssid(wlanhdr), get_bssid(&padapter->mlmepriv), ETH_ALEN));
126
127         pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID && (_rtw_memcmp(get_da(wlanhdr), myid(&padapter->eeprompriv), ETH_ALEN));
128
129         pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID && (GetFrameSubType(wlanhdr) == WIFI_BEACON);
130
131         if(pkt_info.bPacketBeacon){
132                 if(check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _TRUE){                            
133                         sa = padapter->mlmepriv.cur_network.network.MacAddress;
134                         #if 0
135                         {                                       
136                                 DBG_8192C("==> rx beacon from AP[%02x:%02x:%02x:%02x:%02x:%02x]\n",
137                                         sa[0],sa[1],sa[2],sa[3],sa[4],sa[5]);                                   
138                         }
139                         #endif
140                 }
141                 //to do Ad-hoc
142         }
143         else{
144                 sa = get_sa(wlanhdr);
145         }                       
146                 
147         pkt_info.StationID = 0xFF;
148         
149         pstapriv = &padapter->stapriv;
150         psta = rtw_get_stainfo(pstapriv, sa);
151         if (psta)
152         {
153                 pkt_info.StationID = psta->mac_id;
154                 //DBG_8192C("%s ==> StationID(%d)\n",__FUNCTION__,pkt_info.StationID);
155         }
156         pkt_info.Rate = pattrib->mcs_rate;
157                 
158
159         //rtl8192c_query_rx_phy_status(precvframe, pphy_status);
160         //_enter_critical_bh(&pHalData->odm_stainfo_lock, &irqL);
161         ODM_PhyStatusQuery(&pHalData->odmpriv,pPHYInfo,(u8 *)pphy_status,&(pkt_info));
162         //_exit_critical_bh(&pHalData->odm_stainfo_lock, &irqL);
163         precvframe->u.hdr.psta = NULL;
164         if (pkt_info.bPacketMatchBSSID &&
165                 (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE))
166         {
167                 if (psta)
168                 { 
169                         precvframe->u.hdr.psta = psta;
170                         rtl8192c_process_phy_info(padapter, precvframe);
171               }
172         }
173         else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon)
174         {
175                 if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == _TRUE)
176                 {
177                         if (psta)
178                         {
179                                 precvframe->u.hdr.psta = psta;
180                         }
181                 }
182                 rtl8192c_process_phy_info(padapter, precvframe);             
183         }
184 }
185
186 static s32 pre_recv_entry(union recv_frame *precvframe, struct recv_buf *precvbuf, struct phy_stat *pphy_status)
187 {       
188         s32 ret=_SUCCESS;
189 #ifdef CONFIG_CONCURRENT_MODE   
190         u8 *primary_myid, *secondary_myid, *paddr1;
191         union recv_frame        *precvframe_if2 = NULL;
192         _adapter *primary_padapter = precvframe->u.hdr.adapter;
193         _adapter *secondary_padapter = primary_padapter->pbuddy_adapter;
194         struct recv_priv *precvpriv = &primary_padapter->recvpriv;
195         _queue *pfree_recv_queue = &precvpriv->free_recv_queue;
196         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(primary_padapter);
197
198         if(!secondary_padapter)
199                 return ret;
200
201         paddr1 = GetAddr1Ptr(precvframe->u.hdr.rx_data);
202
203         if(IS_MCAST(paddr1) == _FALSE)//unicast packets
204         {
205                 //primary_myid = myid(&primary_padapter->eeprompriv);
206                 secondary_myid = myid(&secondary_padapter->eeprompriv);
207
208                 if(_rtw_memcmp(paddr1, secondary_myid, ETH_ALEN))
209                 {                       
210                         //change to secondary interface
211                         precvframe->u.hdr.adapter = secondary_padapter;
212                 }       
213
214                 //ret = recv_entry(precvframe);
215
216         }
217         else // Handle BC/MC Packets    
218         {
219                 //clone/copy to if2
220                 _pkt     *pkt_copy = NULL;
221                 struct rx_pkt_attrib *pattrib = NULL;
222                 
223                 precvframe_if2 = rtw_alloc_recvframe(pfree_recv_queue);
224
225                 if(!precvframe_if2)
226                         return _FAIL;
227                 
228                 precvframe_if2->u.hdr.adapter = secondary_padapter;
229                 _rtw_memcpy(&precvframe_if2->u.hdr.attrib, &precvframe->u.hdr.attrib, sizeof(struct rx_pkt_attrib));
230                 pattrib = &precvframe_if2->u.hdr.attrib;
231
232                 //driver need to set skb len for rtw_skb_copy().
233                 //If skb->len is zero, rtw_skb_copy() will not copy data from original skb.
234                 skb_put(precvframe->u.hdr.pkt, pattrib->pkt_len);
235
236                 pkt_copy = rtw_skb_copy(precvframe->u.hdr.pkt);
237                 if (pkt_copy == NULL)
238                 {
239                         if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0))
240                         {                               
241                                 DBG_8192C("pre_recv_entry(): rtw_skb_copy fail , drop frag frame \n");
242                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
243                                 return ret;
244                         }
245
246                         pkt_copy = rtw_skb_clone(precvframe->u.hdr.pkt);
247                         if(pkt_copy == NULL)
248                         {
249                                 DBG_8192C("pre_recv_entry(): rtw_skb_clone fail , drop frame\n");
250                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
251                                 return ret;
252                         }
253                 }
254                 
255                 pkt_copy->dev = secondary_padapter->pnetdev;
256
257                 precvframe_if2->u.hdr.pkt = pkt_copy;
258                 precvframe_if2->u.hdr.rx_head = pkt_copy->head;
259                 precvframe_if2->u.hdr.rx_data = pkt_copy->data;
260                 precvframe_if2->u.hdr.rx_tail = skb_tail_pointer(pkt_copy);
261                 precvframe_if2->u.hdr.rx_end = skb_end_pointer(pkt_copy);
262                 precvframe_if2->u.hdr.len = pkt_copy->len;
263
264                 //recvframe_put(precvframe_if2, pattrib->pkt_len);
265
266                 if ( pHalData->ReceiveConfig & RCR_APPFCS)
267                         recvframe_pull_tail(precvframe_if2, IEEE80211_FCS_LEN);
268
269                 if (pattrib->physt) 
270                         update_recvframe_phyinfo(precvframe_if2, pphy_status);
271
272                 if(rtw_recv_entry(precvframe_if2) != _SUCCESS)
273                 {
274                         RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
275                                 ("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n"));
276                 }
277         }
278
279         if (precvframe->u.hdr.attrib.physt)
280                 update_recvframe_phyinfo(precvframe, pphy_status);
281
282         ret = rtw_recv_entry(precvframe);
283 #endif
284
285         return ret;
286
287 }
288
289
290 #ifdef CONFIG_SDIO_RX_COPY
291 #ifdef CONFIG_DIRECT_RECV
292 void rtl8723as_recv(PADAPTER padapter, struct recv_buf *precvbuf)
293 {
294         //PADAPTER                      padapter;
295         PHAL_DATA_TYPE          pHalData;
296         struct recv_priv                *precvpriv;
297         //struct recv_buf               *precvbuf;
298         union recv_frame                *precvframe;
299         struct recv_frame_hdr   *phdr;
300         struct rx_pkt_attrib    *pattrib;
301         _irqL   irql;
302         u8              *ptr;
303         u32             pkt_len, pkt_offset, skb_len, alloc_sz;
304         _pkt            *pkt_copy = NULL;
305         u8              shift_sz = 0, rx_report_sz = 0;
306
307         pHalData = GET_HAL_DATA(padapter);
308         precvpriv = &padapter->recvpriv;
309
310         ptr = precvbuf->pdata;
311
312         while (ptr < precvbuf->ptail)
313         {
314                 precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
315                 if (precvframe == NULL) {
316                         RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: no enough recv frame!\n",__FUNCTION__));
317                         break;
318                 }
319
320                 //rx desc parsing
321                 update_recvframe_attrib(precvframe, (struct recv_stat*)ptr);
322
323                 pattrib = &precvframe->u.hdr.attrib;
324
325                 // fix Hardware RX data error, drop whole recv_buffer
326                 if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err)
327                 {
328                         DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
329
330                         rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
331                         break;
332                 }
333
334                 if (pHalData->ReceiveConfig & RCR_APP_BA_SSN)
335                         rx_report_sz = RXDESC_SIZE + 4 + pattrib->drvinfo_sz;
336                 else
337                         rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz;
338
339                 pkt_offset = rx_report_sz + pattrib->pkt_len;
340
341                 if ((ptr + pkt_offset) > precvbuf->ptail) {
342                         DBG_8192C("%s()-%d: : next pkt len(%p,%d) exceed ptail(%p)!\n", __FUNCTION__, __LINE__, ptr, pkt_offset, precvbuf->ptail);
343                         rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
344                         break;
345                 }
346
347                 if ((pattrib->crc_err) || (pattrib->icv_err))
348                 {
349                         #ifdef CONFIG_MP_INCLUDED
350                         if (padapter->registrypriv.mp_mode == 1)
351                         {
352                                 if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0))
353                                 {
354                                         if (pattrib->crc_err == 1)
355                                                 padapter->mppriv.rx_crcerrpktcount++;
356                                 }
357                         }
358                         #endif
359                         DBG_8192C("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err);
360                         rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
361                 }
362                 else
363                 {
364                         //      Modified by Albert 20101213
365                         //      For 8 bytes IP header alignment.
366                         if (pattrib->qos)       //      Qos data, wireless lan header length is 26
367                         {
368                                 shift_sz = 6;
369                         }
370                         else
371                         {
372                                 shift_sz = 0;
373                         }
374
375                         skb_len = pattrib->pkt_len;
376
377                         // for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet.
378                         // modify alloc_sz for recvive crc error packet by thomas 2011-06-02
379                         if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)){
380                                 //alloc_sz = 1664;      //1664 is 128 alignment.
381                                 if(skb_len <= 1650)
382                                         alloc_sz = 1664;
383                                 else
384                                         alloc_sz = skb_len + 14;
385                         }
386                         else {
387                                         alloc_sz = skb_len;
388                                         //      6 is for IP header 8 bytes alignment in QoS packet case.
389                                         //      8 is for skb->data 4 bytes alignment.
390                                         alloc_sz += 14;
391                         }
392
393                         pkt_copy = rtw_skb_alloc(alloc_sz);
394
395                         if(pkt_copy)
396                         {
397                                 pkt_copy->dev = padapter->pnetdev;
398                                 precvframe->u.hdr.pkt = pkt_copy;
399                                 skb_reserve( pkt_copy, 8 - ((SIZE_PTR)( pkt_copy->data ) & 7 ));//force pkt_copy->data at 8-byte alignment address
400                                 skb_reserve( pkt_copy, shift_sz );//force ip_hdr at 8-byte alignment address according to shift_sz.
401                                 _rtw_memcpy(pkt_copy->data, (ptr + rx_report_sz), skb_len);
402                                 precvframe->u.hdr.rx_head = pkt_copy->head;
403                                 precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_copy->data;
404                                 precvframe->u.hdr.rx_end = skb_end_pointer(pkt_copy);
405                         }
406                         else
407                         {
408                                 if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0))
409                                 {
410                                         DBG_8192C("rtl8723as_recv_tasklet: alloc_skb fail , drop frag frame \n");
411                                         rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
412                                         break;
413                                 }
414
415                                 precvframe->u.hdr.pkt = rtw_skb_clone(precvbuf->pskb);
416                                 if(precvframe->u.hdr.pkt)
417                                 {
418                                         _pkt    *pkt_clone = precvframe->u.hdr.pkt;
419
420                                         pkt_clone->data = ptr + rx_report_sz;
421                                         skb_reset_tail_pointer(pkt_clone);
422                                         precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail
423                                                         = pkt_clone->data;
424                                         precvframe->u.hdr.rx_end =  pkt_clone->data + skb_len;
425                                 }
426                                 else
427                                 {
428                                         DBG_8192C("rtl8723as_recv_tasklet: rtw_skb_clone fail\n");
429                                         rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
430                                         break;
431                                 }
432                         }
433
434                         recvframe_put(precvframe, skb_len);
435                         //recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE);
436
437                         if (pHalData->ReceiveConfig & RCR_APPFCS)
438                                 recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
439
440                         // move to drv info position
441                         ptr += RXDESC_SIZE;
442
443                                 // update drv info
444                         if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
445                                 //rtl8723s_update_bassn(padapter, pdrvinfo);
446                                 ptr += 4;
447                         }
448
449 #ifdef CONFIG_CONCURRENT_MODE
450                         if(rtw_buddy_adapter_up(padapter))
451                         {
452                                 if(pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS)
453                                 {
454                                         RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
455                                                 ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n"));
456                                 }
457                         }
458                         else
459 #endif
460                         {
461                                 if (pattrib->physt)
462                                         update_recvframe_phyinfo(precvframe, (struct phy_stat*)ptr);
463
464                                 if (rtw_recv_entry(precvframe) != _SUCCESS)
465                                 {
466                                         RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n",__FUNCTION__));
467                                 }
468                         }
469                 }
470
471                 // Page size of receive package is 128 bytes alignment =>DMA AGG
472                 // refer to _InitTransferPageSize()
473                 pkt_offset = _RND128(pkt_offset);
474                 precvbuf->pdata += pkt_offset;
475                 ptr = precvbuf->pdata;
476                 precvframe = NULL;
477                 pkt_copy = NULL;
478                 
479         }
480
481         rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
482
483 }
484 #endif //CONFIG_DIRECT_RECV
485
486 static void rtl8723as_recv_tasklet(void *priv)
487 {
488         PADAPTER                        padapter;
489         PHAL_DATA_TYPE          pHalData;
490         struct recv_priv                *precvpriv;
491         struct recv_buf         *precvbuf;
492         union recv_frame                *precvframe;
493         struct recv_frame_hdr   *phdr;
494         struct rx_pkt_attrib    *pattrib;
495         _irqL   irql;
496         u8              *ptr;
497         u32             pkt_len, pkt_offset, skb_len, alloc_sz;
498         _pkt            *pkt_copy = NULL;
499         u8              shift_sz = 0, rx_report_sz = 0;
500
501
502         padapter = (PADAPTER)priv;
503         pHalData = GET_HAL_DATA(padapter);
504         precvpriv = &padapter->recvpriv;
505         
506         do {
507                 precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
508                 if (NULL == precvbuf) break;
509
510                 ptr = precvbuf->pdata;
511
512                 while (ptr < precvbuf->ptail)
513                 {
514                         precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
515                         if (precvframe == NULL) {
516                                 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: no enough recv frame!\n",__FUNCTION__));
517                                 rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
518
519                                 // The case of can't allocte recvframe should be temporary,
520                                 // schedule again and hope recvframe is available next time.
521 #ifdef PLATFORM_LINUX
522                                 tasklet_schedule(&precvpriv->recv_tasklet);
523 #endif
524                                 return;
525                         }
526
527                         //rx desc parsing
528                         update_recvframe_attrib(precvframe, (struct recv_stat*)ptr);
529
530                         pattrib = &precvframe->u.hdr.attrib;
531
532                         // fix Hardware RX data error, drop whole recv_buffer
533                         if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err)
534                         {
535                                 DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
536
537                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
538                                 break;
539                         }
540
541                         if (pHalData->ReceiveConfig & RCR_APP_BA_SSN)
542                                 rx_report_sz = RXDESC_SIZE + 4 + pattrib->drvinfo_sz;
543                         else
544                                 rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz;
545
546                         pkt_offset = rx_report_sz + pattrib->pkt_len;
547
548                         if ((ptr + pkt_offset) > precvbuf->ptail) {
549                                 DBG_8192C("%s()-%d: : next pkt len(%p,%d) exceed ptail(%p)!\n", __FUNCTION__, __LINE__, ptr, pkt_offset, precvbuf->ptail);
550                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
551                                 break;
552                         }
553
554                         if ((pattrib->crc_err) || (pattrib->icv_err))
555                         {
556                                 #ifdef CONFIG_MP_INCLUDED
557                                 if (padapter->registrypriv.mp_mode == 1)
558                                 {
559                                         if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0))
560                                         {
561                                                 if (pattrib->crc_err == 1)
562                                                         padapter->mppriv.rx_crcerrpktcount++;
563                                         }
564                                 }
565                                 #endif
566                                 DBG_8192C("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err);
567                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
568                         }
569                         else
570                         {
571                                 //      Modified by Albert 20101213
572                                 //      For 8 bytes IP header alignment.
573                                 if (pattrib->qos)       //      Qos data, wireless lan header length is 26
574                                 {
575                                         shift_sz = 6;
576                                 }
577                                 else
578                                 {
579                                         shift_sz = 0;
580                                 }
581
582                                 skb_len = pattrib->pkt_len;
583
584                                 // for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet.
585                                 // modify alloc_sz for recvive crc error packet by thomas 2011-06-02
586                                 if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)){
587                                         //alloc_sz = 1664;      //1664 is 128 alignment.
588                                         if(skb_len <= 1650)
589                                                 alloc_sz = 1664;
590                                         else
591                                                 alloc_sz = skb_len + 14;
592                                 }
593                                 else {
594                                         alloc_sz = skb_len;
595                                         //      6 is for IP header 8 bytes alignment in QoS packet case.
596                                         //      8 is for skb->data 4 bytes alignment.
597                                         alloc_sz += 14;
598                                 }
599
600                                 pkt_copy = rtw_skb_alloc(alloc_sz);
601
602                                 if(pkt_copy)
603                                 {
604                                         pkt_copy->dev = padapter->pnetdev;
605                                         precvframe->u.hdr.pkt = pkt_copy;
606                                         skb_reserve( pkt_copy, 8 - ((SIZE_PTR)( pkt_copy->data ) & 7 ));//force pkt_copy->data at 8-byte alignment address
607                                         skb_reserve( pkt_copy, shift_sz );//force ip_hdr at 8-byte alignment address according to shift_sz.
608                                         _rtw_memcpy(pkt_copy->data, (ptr + rx_report_sz), skb_len);
609                                         precvframe->u.hdr.rx_head = pkt_copy->head;
610                                         precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_copy->data;
611                                         precvframe->u.hdr.rx_end = skb_end_pointer(pkt_copy);
612                                 }
613                                 else
614                                 {
615                                         if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0))
616                                         {                               
617                                                 DBG_8192C("rtl8723as_recv_tasklet: alloc_skb fail , drop frag frame \n");
618                                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
619                                                 break;
620                                         }
621                                         
622                                         precvframe->u.hdr.pkt = rtw_skb_clone(precvbuf->pskb);
623                                         if(precvframe->u.hdr.pkt)
624                                         {
625                                                 _pkt    *pkt_clone = precvframe->u.hdr.pkt;
626
627                                                 pkt_clone->data = ptr + rx_report_sz;
628                                                 skb_reset_tail_pointer(pkt_clone);
629                                                 precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail 
630                                                         = pkt_clone->data;
631                                                 precvframe->u.hdr.rx_end =  pkt_clone->data + skb_len;
632                                         }
633                                         else
634                                         {
635                                                 DBG_8192C("rtl8723as_recv_tasklet: rtw_skb_clone fail\n");
636                                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
637                                                 break;
638                                         }
639                                 }
640
641                                 recvframe_put(precvframe, skb_len);
642                                 //recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE);
643
644                                 if (pHalData->ReceiveConfig & RCR_APPFCS)
645                                         recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
646
647                                 // move to drv info position
648                                 ptr += RXDESC_SIZE;
649
650                                 // update drv info
651                                 if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
652                                         //rtl8723s_update_bassn(padapter, pdrvinfo);
653                                         ptr += 4;
654                                 }
655
656 #ifdef CONFIG_CONCURRENT_MODE
657                                 if(rtw_buddy_adapter_up(padapter))
658                                 {
659                                         if(pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS)
660                                         {
661                                                 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
662                                                         ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n"));
663                                         }
664                                 }
665                                 else
666 #endif
667                                 {
668                                         if (pattrib->physt)
669                                                 update_recvframe_phyinfo(precvframe, (struct phy_stat*)ptr);
670
671                                         if (rtw_recv_entry(precvframe) != _SUCCESS)
672                                         {
673                                                 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n",__FUNCTION__));
674                                         }
675                                 }
676                         }
677
678                         // Page size of receive package is 128 bytes alignment =>DMA AGG
679                         // refer to _InitTransferPageSize()
680                         pkt_offset = _RND128(pkt_offset);
681                         precvbuf->pdata += pkt_offset;
682                         ptr = precvbuf->pdata;
683                         precvframe = NULL;
684                         pkt_copy = NULL;
685                 }
686
687                 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
688         } while (1);
689
690 }
691 #else
692 static void rtl8723as_recv_tasklet(void *priv)
693 {
694         PADAPTER                                padapter;
695         PHAL_DATA_TYPE                  pHalData;
696         struct recv_priv                *precvpriv;
697         struct recv_buf                 *precvbuf;
698         union recv_frame                *precvframe;
699         struct recv_frame_hdr   *phdr;
700         struct rx_pkt_attrib    *pattrib;
701         u8                      *ptr;
702         _pkt            *ppkt;
703         u32                     pkt_offset;
704         _irqL           irql;
705
706
707         padapter = (PADAPTER)priv;
708         pHalData = GET_HAL_DATA(padapter);
709         precvpriv = &padapter->recvpriv;
710
711         do {
712                 precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
713                 if (NULL == precvbuf) break;
714
715                 ptr = precvbuf->pdata;
716
717                 while (ptr < precvbuf->ptail)
718                 {
719                         precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
720                         if (precvframe == NULL) {
721                                 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("rtl8723as_recv_tasklet: no enough recv frame!\n"));
722                                 rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
723
724                                 // The case of can't allocte recvframe should be temporary,
725                                 // schedule again and hope recvframe is available next time.
726 #ifdef PLATFORM_LINUX
727                                 tasklet_schedule(&precvpriv->recv_tasklet);
728 #endif
729                                 return;
730                         }
731
732                         phdr = &precvframe->u.hdr;
733                         pattrib = &phdr->attrib;
734
735                         update_recvframe_attrib(precvframe, (struct recv_stat*)ptr);
736
737                         // fix Hardware RX data error, drop whole recv_buffer
738                         if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err)
739                         {
740                                 DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
741                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
742                                 break;
743                         }
744
745                         pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->pkt_len;
746 #if 0 // reduce check to speed up
747                         if ((ptr + pkt_offset) > precvbuf->ptail) {
748                                 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
749                                                 ("%s: next pkt len(%p,%d) exceed ptail(%p)!\n",
750                                                 __FUNCTION__, ptr, pkt_offset, precvbuf->ptail));
751                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
752                                 break;
753                         }
754 #endif
755
756                         if ((pattrib->crc_err) || (pattrib->icv_err))
757                         {
758                                 #ifdef CONFIG_MP_INCLUDED
759                                 if (padapter->registrypriv.mp_mode == 1)
760                                 {
761                                         if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0))
762                                         {
763                                                 if (pattrib->crc_err == 1)
764                                                         padapter->mppriv.rx_crcerrpktcount++;
765                                         }
766                                 }
767                                 #endif
768                                 DBG_8192C("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err);
769                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
770                         }
771                         else
772                         {
773                                 ppkt = rtw_skb_clone(precvbuf->pskb);
774                                 if (ppkt == NULL)
775                                 {
776                                         RT_TRACE(_module_rtl871x_recv_c_, _drv_crit_, ("rtl8723as_recv_tasklet: no enough memory to allocate SKB!\n"));
777                                         rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
778                                         rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
779
780                                         // The case of can't allocte skb is serious and may never be recovered,
781                                         // once bDriverStopped is enable, this task should be stopped.
782                                         if (padapter->bDriverStopped == _FALSE) {
783 #ifdef PLATFORM_LINUX
784                                                 tasklet_schedule(&precvpriv->recv_tasklet);
785 #endif
786                                         }
787
788                                         return;
789                                 }
790
791                                 phdr->pkt = ppkt;
792                                 phdr->len = 0;
793                                 phdr->rx_head = precvbuf->phead;
794                                 phdr->rx_data = phdr->rx_tail = precvbuf->pdata;
795                                 phdr->rx_end = precvbuf->pend;
796                                 recvframe_put(precvframe, pkt_offset);
797                                 recvframe_pull(precvframe, RXDESC_SIZE + pattrib->drvinfo_sz);
798                                 if (pHalData->ReceiveConfig & RCR_APPFCS)
799                                         recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
800
801                                 // move to drv info position
802                                 ptr += RXDESC_SIZE;
803
804                                 // update drv info
805                                 if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
806 //                                      rtl8723s_update_bassn(padapter, pdrvinfo);
807                                         ptr += 4;
808                                 }
809
810 #ifdef CONFIG_CONCURRENT_MODE
811                                 if(rtw_buddy_adapter_up(padapter))
812                                 {
813                                         if(pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS)
814                                         {
815                                                 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
816                                                         ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n"));
817                                         }
818                                 }
819                                 else
820 #endif
821                                 {
822                                         if (pattrib->physt)
823                                                 update_recvframe_phyinfo(precvframe, (struct phy_stat*)ptr);
824
825                                         if (rtw_recv_entry(precvframe) != _SUCCESS)
826                                         {
827                                                 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("rtl8723as_recv_tasklet: rtw_recv_entry(precvframe) != _SUCCESS\n"));
828                                         }
829                                 }
830                         }
831
832                         // Page size of receive package is 128 bytes alignment => DMA agg
833                         // refer to _InitTransferPageSize()
834                         pkt_offset = _RND128(pkt_offset);
835                         precvbuf->pdata += pkt_offset;
836                         ptr = precvbuf->pdata;
837                 }
838
839                 rtw_skb_free(precvbuf->pskb);
840                 precvbuf->pskb = NULL;
841                 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
842         } while (1);
843 }
844 #endif
845
846 /*
847  * Initialize recv private variable for hardware dependent
848  * 1. recv buf
849  * 2. recv tasklet
850  *
851  */
852 s32 rtl8723as_init_recv_priv(PADAPTER padapter)
853 {
854         s32                     res;
855         u32                     i, n;
856         struct recv_priv        *precvpriv;
857         struct recv_buf         *precvbuf;
858
859
860         res = _SUCCESS;
861         precvpriv = &padapter->recvpriv;
862
863         //3 1. init recv buffer
864         _rtw_init_queue(&precvpriv->free_recv_buf_queue);
865         _rtw_init_queue(&precvpriv->recv_buf_pending_queue);
866
867         n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
868         precvpriv->pallocated_recv_buf = rtw_zmalloc(n);
869         if (precvpriv->pallocated_recv_buf == NULL) {
870                 res = _FAIL;
871                 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("alloc recv_buf fail!\n"));
872                 goto exit;
873         }
874
875         precvpriv->precv_buf = (u8*)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4);
876
877         // init each recv buffer
878         precvbuf = (struct recv_buf*)precvpriv->precv_buf;
879         for (i = 0; i < NR_RECVBUFF; i++)
880         {
881                 res = initrecvbuf(precvbuf, padapter);
882                 if (res == _FAIL)
883                         break;
884
885                 res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
886                 if (res == _FAIL) {
887                         freerecvbuf(precvbuf);
888                         break;
889                 }
890
891 #ifdef CONFIG_SDIO_RX_COPY
892                 if (precvbuf->pskb == NULL) {
893                         SIZE_PTR tmpaddr=0;
894                         SIZE_PTR alignment=0;
895
896                         precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
897
898                         if(precvbuf->pskb)
899                         {
900                                 precvbuf->pskb->dev = padapter->pnetdev;
901
902                                 tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
903                                 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
904                                 skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
905                         }
906
907                         if (precvbuf->pskb == NULL) {
908                                 DBG_871X("%s: alloc_skb fail!\n", __FUNCTION__);
909                         }
910                 }
911 #endif
912
913                 rtw_list_insert_tail(&precvbuf->list, &precvpriv->free_recv_buf_queue.queue);
914
915                 precvbuf++;
916         }
917         precvpriv->free_recv_buf_queue_cnt = i;
918
919         if (res == _FAIL)
920                 goto initbuferror;
921
922         //3 2. init tasklet
923 #ifdef PLATFORM_LINUX
924         tasklet_init(&precvpriv->recv_tasklet,
925              (void(*)(unsigned long))rtl8723as_recv_tasklet,
926              (unsigned long)padapter);
927 #endif
928
929         goto exit;
930
931 initbuferror:
932         precvbuf = (struct recv_buf*)precvpriv->precv_buf;
933         if (precvbuf) {
934                 n = precvpriv->free_recv_buf_queue_cnt;
935                 precvpriv->free_recv_buf_queue_cnt = 0;
936                 for (i = 0; i < n ; i++)
937                 {
938                         rtw_list_delete(&precvbuf->list);
939                         rtw_os_recvbuf_resource_free(padapter, precvbuf);
940                         freerecvbuf(precvbuf);
941                         precvbuf++;
942                 }
943                 precvpriv->precv_buf = NULL;
944         }
945
946         if (precvpriv->pallocated_recv_buf) {
947                 n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
948                 rtw_mfree(precvpriv->pallocated_recv_buf, n);
949                 precvpriv->pallocated_recv_buf = NULL;
950         }
951
952 exit:
953         return res;
954 }
955
956 /*
957  * Free recv private variable of hardware dependent
958  * 1. recv buf
959  * 2. recv tasklet
960  *
961  */
962 void rtl8723as_free_recv_priv(PADAPTER padapter)
963 {
964         u32                     i, n;
965         struct recv_priv        *precvpriv;
966         struct recv_buf         *precvbuf;
967
968
969         precvpriv = &padapter->recvpriv;
970
971         //3 1. kill tasklet
972 #ifdef PLATFORM_LINUX
973         tasklet_kill(&precvpriv->recv_tasklet);
974 #endif
975
976         //3 2. free all recv buffers
977         precvbuf = (struct recv_buf*)precvpriv->precv_buf;
978         if (precvbuf) {
979                 n = NR_RECVBUFF;
980                 precvpriv->free_recv_buf_queue_cnt = 0;
981                 for (i = 0; i < n ; i++)
982                 {
983                         rtw_list_delete(&precvbuf->list);
984                         rtw_os_recvbuf_resource_free(padapter, precvbuf);
985                         freerecvbuf(precvbuf);
986                         precvbuf++;
987                 }
988                 precvpriv->precv_buf = NULL;
989         }
990
991         if (precvpriv->pallocated_recv_buf) {
992                 n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
993                 rtw_mfree(precvpriv->pallocated_recv_buf, n);
994                 precvpriv->pallocated_recv_buf = NULL;
995         }
996 }
997