add rk3288 pinctrl dts code
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rtl8723bs / hal / rtl8723b / sdio / rtl8723bs_recv.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 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 _RTL8723BS_RECV_C_
21
22 #include <rtl8723b_hal.h>
23
24
25 static s32 initrecvbuf(struct recv_buf *precvbuf, PADAPTER padapter)
26 {
27         _rtw_init_listhead(&precvbuf->list);
28         _rtw_spinlock_init(&precvbuf->recvbuf_lock);
29
30         precvbuf->adapter = padapter;
31
32         return _SUCCESS;
33 }
34
35 static void freerecvbuf(struct recv_buf *precvbuf)
36 {
37         _rtw_spinlock_free(&precvbuf->recvbuf_lock);
38 }
39
40 static void update_recvframe_attrib(
41         PADAPTER padapter,
42         union recv_frame *precvframe,
43         struct recv_stat *prxstat)
44 {
45         struct rx_pkt_attrib    *pattrib;
46         struct recv_stat        report;
47         PRXREPORT prxreport = (PRXREPORT)&report;
48         
49         report.rxdw0 = le32_to_cpu(prxstat->rxdw0);
50         report.rxdw1 = le32_to_cpu(prxstat->rxdw1);
51         report.rxdw2 = le32_to_cpu(prxstat->rxdw2);
52         report.rxdw3 = le32_to_cpu(prxstat->rxdw3);
53         report.rxdw4 = le32_to_cpu(prxstat->rxdw4);
54         report.rxdw5 = le32_to_cpu(prxstat->rxdw5);
55         
56         pattrib = &precvframe->u.hdr.attrib;
57         _rtw_memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
58
59         // update rx report to recv_frame attribute
60         pattrib->pkt_rpt_type = prxreport->c2h_ind?C2H_PACKET:NORMAL_RX;
61 //      DBG_871X("%s: pkt_rpt_type=%d\n", __func__, pattrib->pkt_rpt_type);
62
63         if (pattrib->pkt_rpt_type == NORMAL_RX)
64         {
65                 // Normal rx packet
66                 // update rx report to recv_frame attribute
67                 pattrib->pkt_len = (u16)prxreport->pktlen;
68                 pattrib->drvinfo_sz = (u8)(prxreport->drvinfosize << 3);
69                 pattrib->physt = (u8)prxreport->physt;
70
71                 pattrib->crc_err = (u8)prxreport->crc32;
72                 pattrib->icv_err = (u8)prxreport->icverr;
73
74                 pattrib->bdecrypted = (u8)(prxreport->swdec ? 0 : 1);
75                 pattrib->encrypt = (u8)prxreport->security;
76
77                 pattrib->qos = (u8)prxreport->qos;
78                 pattrib->priority = (u8)prxreport->tid;
79
80                 pattrib->amsdu = (u8)prxreport->amsdu;
81
82                 pattrib->seq_num = (u16)prxreport->seq;
83                 pattrib->frag_num = (u8)prxreport->frag;
84                 pattrib->mfrag = (u8)prxreport->mf;
85                 pattrib->mdata = (u8)prxreport->md;
86
87                 pattrib->data_rate = (u8)prxreport->rx_rate;
88         }
89         else
90         {
91                 pattrib->pkt_len = (u16)prxreport->pktlen;
92         }
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=NULL;
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.DataRate = pattrib->data_rate;
157
158         //rtl8723b_query_rx_phy_status(precvframe, pphy_status);
159         //_enter_critical_bh(&pHalData->odm_stainfo_lock, &irqL);
160         ODM_PhyStatusQuery(&pHalData->odmpriv,pPHYInfo,(u8 *)pphy_status,&(pkt_info));
161         //_exit_critical_bh(&pHalData->odm_stainfo_lock, &irqL);
162         precvframe->u.hdr.psta = NULL;
163         if (pkt_info.bPacketMatchBSSID &&
164                 (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE))
165         {
166                 if (psta)
167                 {
168                         precvframe->u.hdr.psta = psta;
169                         rtl8723b_process_phy_info(padapter, precvframe);
170               }
171         }
172         else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon)
173         {
174                 if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == _TRUE)
175                 {
176                         if (psta)
177                         {
178                                 precvframe->u.hdr.psta = psta;
179                         }
180                 }
181                 rtl8723b_process_phy_info(padapter, precvframe);
182         }
183 }
184
185 static s32 pre_recv_entry(union recv_frame *precvframe, struct recv_buf *precvbuf, struct phy_stat *pphy_status)
186 {
187         s32 ret=_SUCCESS;
188 #ifdef CONFIG_CONCURRENT_MODE
189         u8 *primary_myid, *secondary_myid, *paddr1;
190         union recv_frame        *precvframe_if2 = NULL;
191         _adapter *primary_padapter = precvframe->u.hdr.adapter;
192         _adapter *secondary_padapter = primary_padapter->pbuddy_adapter;
193         struct recv_priv *precvpriv = &primary_padapter->recvpriv;
194         _queue *pfree_recv_queue = &precvpriv->free_recv_queue;
195         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(primary_padapter);
196
197         if(!secondary_padapter)
198                 return ret;
199
200         paddr1 = GetAddr1Ptr(precvframe->u.hdr.rx_data);
201
202         if(IS_MCAST(paddr1) == _FALSE)//unicast packets
203         {
204                 //primary_myid = myid(&primary_padapter->eeprompriv);
205                 secondary_myid = myid(&secondary_padapter->eeprompriv);
206
207                 if(_rtw_memcmp(paddr1, secondary_myid, ETH_ALEN))
208                 {
209                         //change to secondary interface
210                         precvframe->u.hdr.adapter = secondary_padapter;
211                 }
212
213                 //ret = recv_entry(precvframe);
214
215         }
216         else // Handle BC/MC Packets
217         {
218                 //clone/copy to if2
219                 _pkt     *pkt_copy = NULL;
220                 struct rx_pkt_attrib *pattrib = NULL;
221
222                 precvframe_if2 = rtw_alloc_recvframe(pfree_recv_queue);
223
224                 if(!precvframe_if2)
225                         return _FAIL;
226
227                 precvframe_if2->u.hdr.adapter = secondary_padapter;
228                 _rtw_memcpy(&precvframe_if2->u.hdr.attrib, &precvframe->u.hdr.attrib, sizeof(struct rx_pkt_attrib));
229                 pattrib = &precvframe_if2->u.hdr.attrib;
230
231                 //driver need to set skb len for skb_copy().
232                 //If skb->len is zero, skb_copy() will not copy data from original skb.
233                 skb_put(precvframe->u.hdr.pkt, pattrib->pkt_len);
234
235                 pkt_copy = rtw_skb_copy( precvframe->u.hdr.pkt);
236                 if (pkt_copy == NULL)
237                 {
238                         if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0))
239                         {
240                                 DBG_8192C("pre_recv_entry(): rtw_skb_copy fail , drop frag frame \n");
241                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
242                                 return ret;
243                         }
244
245                         pkt_copy = rtw_skb_clone( precvframe->u.hdr.pkt);
246                         if(pkt_copy == NULL)
247                         {
248                                 DBG_8192C("pre_recv_entry(): rtw_skb_clone fail , drop frame\n");
249                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
250                                 return ret;
251                         }
252                 }
253
254                 pkt_copy->dev = secondary_padapter->pnetdev;
255
256                 precvframe_if2->u.hdr.pkt = pkt_copy;
257                 precvframe_if2->u.hdr.rx_head = pkt_copy->head;
258                 precvframe_if2->u.hdr.rx_data = pkt_copy->data;
259                 precvframe_if2->u.hdr.rx_tail = skb_tail_pointer(pkt_copy);
260                 precvframe_if2->u.hdr.rx_end = skb_end_pointer(pkt_copy);
261                 precvframe_if2->u.hdr.len = pkt_copy->len;
262
263                 //recvframe_put(precvframe_if2, pattrib->pkt_len);
264
265                 if ( pHalData->ReceiveConfig & RCR_APPFCS)
266                         recvframe_pull_tail(precvframe_if2, IEEE80211_FCS_LEN);
267
268                 if (pattrib->physt)
269                         update_recvframe_phyinfo(precvframe_if2, pphy_status);
270
271                 if(rtw_recv_entry(precvframe_if2) != _SUCCESS)
272                 {
273                         RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
274                                 ("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n"));
275                 }
276         }
277
278         if (precvframe->u.hdr.attrib.physt)
279                 update_recvframe_phyinfo(precvframe, pphy_status);
280
281         ret = rtw_recv_entry(precvframe);
282 #endif
283
284         return ret;
285
286 }
287
288 #ifdef CONFIG_C2H_PACKET_EN
289 static void rtl8723bs_c2h_packet_handler(PADAPTER padapter, u8 *pbuf, u16 length)
290 {
291         u8 *tmpBuf=NULL;
292         u8 res = _FALSE;
293
294         if(length == 0)
295                 return;
296         
297         DBG_871X("+%s() length=%d\n", __func__, length);
298
299         tmpBuf = rtw_zmalloc(length);
300         if (tmpBuf == NULL)
301                 return;
302
303         _rtw_memcpy(tmpBuf, pbuf, length);
304
305         res = rtw_c2h_packet_wk_cmd(padapter, tmpBuf, length);
306
307         if (res == _FALSE && tmpBuf != NULL)
308                         rtw_mfree(tmpBuf, length);
309
310         DBG_871X("-%s res(%d)\n", __func__, res);
311
312         return;
313 }
314 #endif
315
316
317 #ifdef CONFIG_SDIO_RX_COPY
318 static void rtl8723bs_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_len, pkt_offset, skb_len, alloc_sz;
330         _pkt            *pkt_copy = NULL;
331         u8              shift_sz = 0, rx_report_sz = 0;
332
333
334         padapter = (PADAPTER)priv;
335         pHalData = GET_HAL_DATA(padapter);
336         precvpriv = &padapter->recvpriv;
337
338         do {
339                 precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
340                 if (NULL == precvbuf) break;
341
342                 ptr = precvbuf->pdata;
343
344                 while (ptr < precvbuf->ptail)
345                 {
346                         precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
347                         if (precvframe == NULL)
348                         {
349                                 DBG_8192C("%s: no enough recv frame!\n", __FUNCTION__);
350                                 rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
351
352                                 // The case of can't allocte recvframe should be temporary,
353                                 // schedule again and hope recvframe is available next time.
354 #ifdef PLATFORM_LINUX
355                                 tasklet_schedule(&precvpriv->recv_tasklet);
356 #endif
357                                 return;
358                         }
359
360                         //rx desc parsing
361                         update_recvframe_attrib(padapter, precvframe, (struct recv_stat*)ptr);
362
363                         pattrib = &precvframe->u.hdr.attrib;
364
365                         // fix Hardware RX data error, drop whole recv_buffer
366                         if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err)
367                         {
368 #if !(MP_DRIVER==1)
369                                 DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
370 #endif
371                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
372                                 break;
373                         }
374
375                         rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz;
376                         pkt_offset = rx_report_sz + pattrib->shift_sz + pattrib->pkt_len;
377
378                         if ((ptr + pkt_offset) > precvbuf->ptail) {
379                                 DBG_8192C("%s()-%d: : next pkt len(%p,%d) exceed ptail(%p)!\n", __FUNCTION__, __LINE__, ptr, pkt_offset, precvbuf->ptail);
380                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
381                                 break;
382                         }
383
384                         if ((pattrib->crc_err) || (pattrib->icv_err))
385                         {
386 #ifdef CONFIG_MP_INCLUDED
387                                 if (padapter->registrypriv.mp_mode == 1)
388                                 {
389                                         if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0))
390                                         {
391                                                 if (pattrib->crc_err == 1)
392                                                         padapter->mppriv.rx_crcerrpktcount++;
393                                         }
394                                 }
395 #endif
396                                 DBG_8192C("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err);
397                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
398                         }
399                         else
400                         {
401                                 //      Modified by Albert 20101213
402                                 //      For 8 bytes IP header alignment.
403                                 if (pattrib->qos)       //      Qos data, wireless lan header length is 26
404                                 {
405                                         shift_sz = 6;
406                                 }
407                                 else
408                                 {
409                                         shift_sz = 0;
410                                 }
411
412                                 skb_len = pattrib->pkt_len;
413
414                                 // for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet.
415                                 // modify alloc_sz for recvive crc error packet by thomas 2011-06-02
416                                 if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)){
417                                         //alloc_sz = 1664;      //1664 is 128 alignment.
418                                         if(skb_len <= 1650)
419                                                 alloc_sz = 1664;
420                                         else
421                                                 alloc_sz = skb_len + 14;
422                                 }
423                                 else {
424                                         alloc_sz = skb_len;
425                                         //      6 is for IP header 8 bytes alignment in QoS packet case.
426                                         //      8 is for skb->data 4 bytes alignment.
427                                         alloc_sz += 14;
428                                 }
429
430                                 pkt_copy = rtw_skb_alloc(alloc_sz);
431
432                                 if(pkt_copy)
433                                 {
434                                         pkt_copy->dev = padapter->pnetdev;
435                                         precvframe->u.hdr.pkt = pkt_copy;
436                                         skb_reserve( pkt_copy, 8 - ((SIZE_PTR)( pkt_copy->data ) & 7 ));//force pkt_copy->data at 8-byte alignment address
437                                         skb_reserve( pkt_copy, shift_sz );//force ip_hdr at 8-byte alignment address according to shift_sz.
438                                         _rtw_memcpy(pkt_copy->data, (ptr + rx_report_sz + pattrib->shift_sz), skb_len);
439                                         precvframe->u.hdr.rx_head = pkt_copy->head;
440                                         precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_copy->data;
441                                         precvframe->u.hdr.rx_end = skb_end_pointer(pkt_copy);
442                                 }
443                                 else
444                                 {
445                                         if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0))
446                                         {
447                                                 DBG_8192C("%s: alloc_skb fail, drop frag frame\n", __FUNCTION__);
448                                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
449                                                 break;
450                                         }
451
452                                         precvframe->u.hdr.pkt = rtw_skb_clone(precvbuf->pskb);
453                                         if(precvframe->u.hdr.pkt)
454                                         {
455                                                 _pkt    *pkt_clone = precvframe->u.hdr.pkt;
456
457                                                 pkt_clone->data = ptr + rx_report_sz + pattrib->shift_sz;
458                                                 skb_reset_tail_pointer(pkt_clone);
459                                                 precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail
460                                                         = pkt_clone->data;
461                                                 precvframe->u.hdr.rx_end =      pkt_clone->data + skb_len;
462                                         }
463                                         else
464                                         {
465                                                 DBG_8192C("%s: rtw_skb_clone fail\n", __FUNCTION__);
466                                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
467                                                 break;
468                                         }
469                                 }
470
471                                 recvframe_put(precvframe, skb_len);
472                                 //recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE);
473
474                                 if (pHalData->ReceiveConfig & RCR_APPFCS)
475                                         recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
476
477                                 // move to drv info position
478                                 ptr += RXDESC_SIZE;
479
480                                 // update drv info
481                                 if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
482                                         //rtl8723s_update_bassn(padapter, pdrvinfo);
483                                         ptr += 4;
484                                 }
485
486 #ifdef CONFIG_C2H_PACKET_EN
487                                 if(pattrib->pkt_rpt_type == NORMAL_RX)//Normal rx packet
488                                 {
489 #endif
490 #ifdef CONFIG_CONCURRENT_MODE
491                                 if(rtw_buddy_adapter_up(padapter))
492                                 {
493                                         if(pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS)
494                                         {
495                                                 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
496                                                         ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n"));
497                                         }
498                                 }
499                                 else
500 #endif
501                                 {
502                                         if (pattrib->physt)
503                                                 update_recvframe_phyinfo(precvframe, (struct phy_stat*)ptr);
504
505                                         if (rtw_recv_entry(precvframe) != _SUCCESS)
506                                         {
507                                                 RT_TRACE(_module_rtl871x_recv_c_, _drv_dump_, ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n",__FUNCTION__));
508                                         }
509                                 }
510 #ifdef CONFIG_C2H_PACKET_EN
511                                 }
512                                 else if(pattrib->pkt_rpt_type == C2H_PACKET)
513                                 {
514                                         C2H_EVT_HDR     C2hEvent;
515                                         
516                                         u16 len_c2h = pattrib->pkt_len;
517                                         u8 *pbuf_c2h = precvframe->u.hdr.rx_data;
518                                         u8 *pdata_c2h;                          
519
520                                         C2hEvent.CmdID = pbuf_c2h[0];
521                                         C2hEvent.CmdSeq = pbuf_c2h[1];
522                                         C2hEvent.CmdLen = (len_c2h -2);
523                                         pdata_c2h = pbuf_c2h+2;
524
525                                         if(C2hEvent.CmdID == C2H_CCX_TX_RPT)
526                                         {
527                                                 CCX_FwC2HTxRpt_8723b(padapter, pdata_c2h, C2hEvent.CmdLen);
528                                         }
529                                         else
530                                         {
531                                                 rtl8723bs_c2h_packet_handler(padapter, precvframe->u.hdr.rx_data, pattrib->pkt_len);
532                                         }
533                                         
534                                         rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
535                                         
536                                 }
537 #endif                          
538                         }
539
540                         pkt_offset = _RND8(pkt_offset);
541                         precvbuf->pdata += pkt_offset;
542                         ptr = precvbuf->pdata;
543                         precvframe = NULL;
544                         pkt_copy = NULL;
545                 }
546
547                 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
548         } while (1);
549
550 }
551 #else
552 static void rtl8723bs_recv_tasklet(void *priv)
553 {
554         PADAPTER                                padapter;
555         PHAL_DATA_TYPE                  pHalData;
556         struct recv_priv                *precvpriv;
557         struct recv_buf                 *precvbuf;
558         union recv_frame                *precvframe;
559         struct recv_frame_hdr   *phdr;
560         struct rx_pkt_attrib    *pattrib;
561         u8                      *ptr;
562         _pkt            *ppkt;
563         u32             pkt_offset;
564         _irqL           irql;
565
566
567         padapter = (PADAPTER)priv;
568         pHalData = GET_HAL_DATA(padapter);
569         precvpriv = &padapter->recvpriv;
570
571         do {
572                 precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
573                 if (NULL == precvbuf) break;
574
575                 ptr = precvbuf->pdata;
576
577                 while (ptr < precvbuf->ptail)
578                 {
579                         precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
580                         if (precvframe == NULL) {
581                                 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("rtl8723bs_recv_tasklet: no enough recv frame!\n"));
582                                 rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
583
584                                 // The case of can't allocte recvframe should be temporary,
585                                 // schedule again and hope recvframe is available next time.
586 #ifdef PLATFORM_LINUX
587                                 tasklet_schedule(&precvpriv->recv_tasklet);
588 #endif
589                                 return;
590                         }
591
592                         phdr = &precvframe->u.hdr;
593                         pattrib = &phdr->attrib;
594
595                         update_recvframe_attrib(padapter, precvframe, (struct recv_stat*)ptr);
596
597 #if 0
598                         {
599                                 int i, len = 64;
600                                 u8 *pptr = ptr;
601
602                                 if((*(pptr + RXDESC_SIZE + pattrib->drvinfo_sz) != 0x80) && (*(pptr + RXDESC_SIZE + pattrib->drvinfo_sz) != 0x40))
603                                 {
604                                         DBG_871X("##############RxDESC############### \n");
605                                         for(i=0; i<32;i=i+16)
606                                                 DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(pptr+i),
607                                                 *(pptr+i+1), *(pptr+i+2) ,*(pptr+i+3) ,*(pptr+i+4),*(pptr+i+5), *(pptr+i+6), *(pptr+i+7), *(pptr+i+8), *(pptr+i+9), *(pptr+i+10),
608                                                  *(pptr+i+11), *(pptr+i+12), *(pptr+i+13), *(pptr+i+14), *(pptr+i+15));
609                                         
610                                         if(pattrib->pkt_len < 100)
611                                                 len = pattrib->pkt_len;
612                                         pptr = ptr + RXDESC_SIZE + pattrib->drvinfo_sz;
613                                         DBG_871X("##############Len=%d############### \n", pattrib->pkt_len);
614                                         for(i=0; i<len;i=i+16)
615                                                 DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(pptr+i),
616                                                 *(pptr+i+1), *(pptr+i+2) ,*(pptr+i+3) ,*(pptr+i+4),*(pptr+i+5), *(pptr+i+6), *(pptr+i+7), *(pptr+i+8), *(pptr+i+9), *(pptr+i+10),
617                                                  *(pptr+i+11), *(pptr+i+12), *(pptr+i+13), *(pptr+i+14), *(pptr+i+15));
618                                         DBG_871X("############################# \n");
619                                 }
620                         }
621 #endif
622
623                         // fix Hardware RX data error, drop whole recv_buffer
624                         if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err)
625                         {
626                                 DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
627                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
628                                 break;
629                         }
630
631                         pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->pkt_len;
632 #if 0 // reduce check to speed up
633                         if ((ptr + pkt_offset) > precvbuf->ptail) {
634                                 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
635                                                 ("%s: next pkt len(%p,%d) exceed ptail(%p)!\n",
636                                                 __FUNCTION__, ptr, pkt_offset, precvbuf->ptail));
637                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
638                                 break;
639                         }
640 #endif
641
642                         if ((pattrib->crc_err) || (pattrib->icv_err))
643                         {
644 #ifdef CONFIG_MP_INCLUDED
645                                 if (padapter->registrypriv.mp_mode == 1)
646                                 {
647                                         if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0))
648                                         {
649                                                 if (pattrib->crc_err == 1)
650                                                         padapter->mppriv.rx_crcerrpktcount++;
651                                         }
652                                 }
653 #endif
654                                 DBG_8192C("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err);
655                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
656                         }
657                         else
658                         {
659                                 ppkt = rtw_skb_clone(precvbuf->pskb);
660                                 if (ppkt == NULL)
661                                 {
662                                         RT_TRACE(_module_rtl871x_recv_c_, _drv_crit_, ("rtl8723bs_recv_tasklet: no enough memory to allocate SKB!\n"));
663                                         rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
664                                         rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
665
666                                         // The case of can't allocte skb is serious and may never be recovered,
667                                         // once bDriverStopped is enable, this task should be stopped.
668                                         if (padapter->bDriverStopped == _FALSE) {
669 #ifdef PLATFORM_LINUX
670                                                 tasklet_schedule(&precvpriv->recv_tasklet);
671 #endif
672                                         }
673
674                                         return;
675                                 }
676
677                                 phdr->pkt = ppkt;
678                                 phdr->len = 0;
679                                 phdr->rx_head = precvbuf->phead;
680                                 phdr->rx_data = phdr->rx_tail = precvbuf->pdata;
681                                 phdr->rx_end = precvbuf->pend;
682                                 recvframe_put(precvframe, pkt_offset);
683                                 recvframe_pull(precvframe, RXDESC_SIZE + pattrib->drvinfo_sz);
684                                 if (pHalData->ReceiveConfig & RCR_APPFCS)
685                                         recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
686
687                                 // move to drv info position
688                                 ptr += RXDESC_SIZE;
689
690                                 // update drv info
691                                 if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
692 //                                      rtl8723s_update_bassn(padapter, pdrvinfo);
693                                         ptr += 4;
694                                 }
695
696                                 if(pattrib->pkt_rpt_type == NORMAL_RX)//Normal rx packet
697                                 {
698 #ifdef CONFIG_CONCURRENT_MODE
699                                 if(rtw_buddy_adapter_up(padapter))
700                                 {
701                                         if(pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS)
702                                         {
703                                                 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
704                                                         ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n"));
705                                         }
706                                 }
707                                 else
708 #endif
709                                 {
710                                         if (pattrib->physt)
711                                                 update_recvframe_phyinfo(precvframe, (struct phy_stat*)ptr);
712
713                                         if (rtw_recv_entry(precvframe) != _SUCCESS)
714                                         {
715                                                         RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("rtl8723bs_recv_tasklet: rtw_recv_entry(precvframe) != _SUCCESS\n"));
716                                         }
717                                 }
718                         }
719 #ifdef CONFIG_C2H_PACKET_EN
720                                 else if(pattrib->pkt_rpt_type == C2H_PACKET)
721                                 {
722                                         rtl8723bs_c2h_packet_handler(padapter, precvframe->u.hdr.rx_data, pattrib->pkt_len);
723                                         rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
724                                 }
725 #endif                          
726                         }
727
728                         pkt_offset = _RND8(pkt_offset);
729                         precvbuf->pdata += pkt_offset;
730                         ptr = precvbuf->pdata;
731                 }
732
733                 rtw_skb_free(precvbuf->pskb);
734                 precvbuf->pskb = NULL;
735                 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
736         } while (1);
737 }
738 #endif
739
740 /*
741  * Initialize recv private variable for hardware dependent
742  * 1. recv buf
743  * 2. recv tasklet
744  *
745  */
746 s32 rtl8723bs_init_recv_priv(PADAPTER padapter)
747 {
748         s32                     res;
749         u32                     i, n;
750         struct recv_priv        *precvpriv;
751         struct recv_buf         *precvbuf;
752
753
754         res = _SUCCESS;
755         precvpriv = &padapter->recvpriv;
756
757         //3 1. init recv buffer
758         _rtw_init_queue(&precvpriv->free_recv_buf_queue);
759         _rtw_init_queue(&precvpriv->recv_buf_pending_queue);
760
761         n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
762         precvpriv->pallocated_recv_buf = rtw_zmalloc(n);
763         if (precvpriv->pallocated_recv_buf == NULL) {
764                 res = _FAIL;
765                 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("alloc recv_buf fail!\n"));
766                 goto exit;
767         }
768
769         precvpriv->precv_buf = (u8*)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4);
770
771         // init each recv buffer
772         precvbuf = (struct recv_buf*)precvpriv->precv_buf;
773         for (i = 0; i < NR_RECVBUFF; i++)
774         {
775                 res = initrecvbuf(precvbuf, padapter);
776                 if (res == _FAIL)
777                         break;
778
779                 res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
780                 if (res == _FAIL) {
781                         freerecvbuf(precvbuf);
782                         break;
783                 }
784
785 #ifdef CONFIG_SDIO_RX_COPY
786                 if (precvbuf->pskb == NULL) {
787                         SIZE_PTR tmpaddr=0;
788                         SIZE_PTR alignment=0;
789
790                         precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
791
792                         if(precvbuf->pskb)
793                         {
794                                 precvbuf->pskb->dev = padapter->pnetdev;
795
796                                 tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
797                                 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
798                                 skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
799                         }
800
801                         if (precvbuf->pskb == NULL) {
802                                 DBG_871X("%s: alloc_skb fail!\n", __FUNCTION__);
803                         }
804                 }
805 #endif
806
807                 rtw_list_insert_tail(&precvbuf->list, &precvpriv->free_recv_buf_queue.queue);
808
809                 precvbuf++;
810         }
811         precvpriv->free_recv_buf_queue_cnt = i;
812
813         if (res == _FAIL)
814                 goto initbuferror;
815
816         //3 2. init tasklet
817 #ifdef PLATFORM_LINUX
818         tasklet_init(&precvpriv->recv_tasklet,
819              (void(*)(unsigned long))rtl8723bs_recv_tasklet,
820              (unsigned long)padapter);
821 #endif
822
823         goto exit;
824
825 initbuferror:
826         precvbuf = (struct recv_buf*)precvpriv->precv_buf;
827         if (precvbuf) {
828                 n = precvpriv->free_recv_buf_queue_cnt;
829                 precvpriv->free_recv_buf_queue_cnt = 0;
830                 for (i = 0; i < n ; i++)
831                 {
832                         rtw_list_delete(&precvbuf->list);
833                         rtw_os_recvbuf_resource_free(padapter, precvbuf);
834                         freerecvbuf(precvbuf);
835                         precvbuf++;
836                 }
837                 precvpriv->precv_buf = NULL;
838         }
839
840         if (precvpriv->pallocated_recv_buf) {
841                 n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
842                 rtw_mfree(precvpriv->pallocated_recv_buf, n);
843                 precvpriv->pallocated_recv_buf = NULL;
844         }
845
846 exit:
847         return res;
848 }
849
850 /*
851  * Free recv private variable of hardware dependent
852  * 1. recv buf
853  * 2. recv tasklet
854  *
855  */
856 void rtl8723bs_free_recv_priv(PADAPTER padapter)
857 {
858         u32                     i, n;
859         struct recv_priv        *precvpriv;
860         struct recv_buf         *precvbuf;
861
862
863         precvpriv = &padapter->recvpriv;
864
865         //3 1. kill tasklet
866 #ifdef PLATFORM_LINUX
867         tasklet_kill(&precvpriv->recv_tasklet);
868 #endif
869
870         //3 2. free all recv buffers
871         precvbuf = (struct recv_buf*)precvpriv->precv_buf;
872         if (precvbuf) {
873                 n = NR_RECVBUFF;
874                 precvpriv->free_recv_buf_queue_cnt = 0;
875                 for (i = 0; i < n ; i++)
876                 {
877                         rtw_list_delete(&precvbuf->list);
878                         rtw_os_recvbuf_resource_free(padapter, precvbuf);
879                         freerecvbuf(precvbuf);
880                         precvbuf++;
881                 }
882                 precvpriv->precv_buf = NULL;
883         }
884
885         if (precvpriv->pallocated_recv_buf) {
886                 n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
887                 rtw_mfree(precvpriv->pallocated_recv_buf, n);
888                 precvpriv->pallocated_recv_buf = NULL;
889         }
890 }
891