1189583af3a5fd612026f9578515cffad16c585f
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / 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 s32 pre_recv_entry(union recv_frame *precvframe, struct recv_buf *precvbuf, struct phy_stat *pphy_status)
41 {
42         s32 ret=_SUCCESS;
43 #ifdef CONFIG_CONCURRENT_MODE
44         u8 *primary_myid, *secondary_myid, *paddr1;
45         union recv_frame        *precvframe_if2 = NULL;
46         _adapter *primary_padapter = precvframe->u.hdr.adapter;
47         _adapter *secondary_padapter = primary_padapter->pbuddy_adapter;
48         struct recv_priv *precvpriv = &primary_padapter->recvpriv;
49         _queue *pfree_recv_queue = &precvpriv->free_recv_queue;
50         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(primary_padapter);
51
52         if(!secondary_padapter)
53                 return ret;
54
55         paddr1 = GetAddr1Ptr(precvframe->u.hdr.rx_data);
56
57         if(IS_MCAST(paddr1) == _FALSE)//unicast packets
58         {
59                 //primary_myid = myid(&primary_padapter->eeprompriv);
60                 secondary_myid = myid(&secondary_padapter->eeprompriv);
61
62                 if(_rtw_memcmp(paddr1, secondary_myid, ETH_ALEN))
63                 {
64                         //change to secondary interface
65                         precvframe->u.hdr.adapter = secondary_padapter;
66                 }
67
68                 //ret = recv_entry(precvframe);
69
70         }
71         else // Handle BC/MC Packets
72         {
73                 //clone/copy to if2
74                 _pkt     *pkt_copy = NULL;
75                 struct rx_pkt_attrib *pattrib = NULL;
76
77                 precvframe_if2 = rtw_alloc_recvframe(pfree_recv_queue);
78
79                 if(!precvframe_if2)
80                         return _FAIL;
81
82                 precvframe_if2->u.hdr.adapter = secondary_padapter;
83                 _rtw_memcpy(&precvframe_if2->u.hdr.attrib, &precvframe->u.hdr.attrib, sizeof(struct rx_pkt_attrib));
84                 pattrib = &precvframe_if2->u.hdr.attrib;
85
86                 //driver need to set skb len for skb_copy().
87                 //If skb->len is zero, skb_copy() will not copy data from original skb.
88                 skb_put(precvframe->u.hdr.pkt, pattrib->pkt_len);
89
90                 pkt_copy = rtw_skb_copy( precvframe->u.hdr.pkt);
91                 if (pkt_copy == NULL)
92                 {
93                         if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0))
94                         {
95                                 DBG_8192C("pre_recv_entry(): rtw_skb_copy fail , drop frag frame \n");
96                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
97                                 ret = _FAIL;
98                                 return ret;
99                         }
100
101                         pkt_copy = rtw_skb_clone( precvframe->u.hdr.pkt);
102                         if(pkt_copy == NULL)
103                         {
104                                 DBG_8192C("pre_recv_entry(): rtw_skb_clone fail , drop frame\n");
105                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
106                                 ret = _FAIL;
107                                 return ret;
108                         }
109                 }
110
111                 pkt_copy->dev = secondary_padapter->pnetdev;
112
113                 precvframe_if2->u.hdr.pkt = pkt_copy;
114                 precvframe_if2->u.hdr.rx_head = pkt_copy->head;
115                 precvframe_if2->u.hdr.rx_data = pkt_copy->data;
116                 precvframe_if2->u.hdr.rx_tail = skb_tail_pointer(pkt_copy);
117                 precvframe_if2->u.hdr.rx_end = skb_end_pointer(pkt_copy);
118                 precvframe_if2->u.hdr.len = pkt_copy->len;
119
120                 //recvframe_put(precvframe_if2, pattrib->pkt_len);
121
122                 if ( pHalData->ReceiveConfig & RCR_APPFCS)
123                         recvframe_pull_tail(precvframe_if2, IEEE80211_FCS_LEN);
124
125                 if (pattrib->physt)
126                         rtl8723b_query_rx_phy_status(precvframe_if2, pphy_status);
127
128                 if(rtw_recv_entry(precvframe_if2) != _SUCCESS)
129                 {
130                         RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
131                                 ("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n"));
132                 }
133         }
134 #endif
135
136         return ret;
137
138 }
139
140 #ifdef CONFIG_SDIO_RX_COPY
141 static void rtl8723bs_recv_tasklet(void *priv)
142 {
143         PADAPTER                        padapter;
144         PHAL_DATA_TYPE          pHalData;
145         struct recv_priv                *precvpriv;
146         struct recv_buf         *precvbuf;
147         union recv_frame                *precvframe;
148         struct recv_frame_hdr   *phdr;
149         struct rx_pkt_attrib    *pattrib;
150         _irqL   irql;
151         u8              *ptr;
152         u32     pkt_len, pkt_offset, skb_len, alloc_sz;
153         _pkt            *pkt_copy = NULL;
154         u8              shift_sz = 0, rx_report_sz = 0;
155
156
157         padapter = (PADAPTER)priv;
158         pHalData = GET_HAL_DATA(padapter);
159         precvpriv = &padapter->recvpriv;
160
161         do {
162                 precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
163                 if (NULL == precvbuf) break;
164
165                 ptr = precvbuf->pdata;
166
167                 while (ptr < precvbuf->ptail)
168                 {
169                         precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
170                         if (precvframe == NULL)
171                         {
172                                 DBG_8192C("%s: no enough recv frame!\n", __FUNCTION__);
173                                 rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
174
175                                 // The case of can't allocte recvframe should be temporary,
176                                 // schedule again and hope recvframe is available next time.
177 #ifdef PLATFORM_LINUX
178                                 tasklet_schedule(&precvpriv->recv_tasklet);
179 #endif
180                                 return;
181                         }
182
183                         //rx desc parsing
184                         rtl8723b_query_rx_desc_status(precvframe, ptr);
185
186                         pattrib = &precvframe->u.hdr.attrib;
187
188                         // fix Hardware RX data error, drop whole recv_buffer
189                         if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err)
190                         {
191 #if !(MP_DRIVER==1)
192                                 DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
193 #endif
194                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
195                                 break;
196                         }
197
198                         rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz;
199                         pkt_offset = rx_report_sz + pattrib->shift_sz + pattrib->pkt_len;
200
201                         if ((ptr + pkt_offset) > precvbuf->ptail) {
202                                 DBG_8192C("%s()-%d: : next pkt len(%p,%d) exceed ptail(%p)!\n", __FUNCTION__, __LINE__, ptr, pkt_offset, precvbuf->ptail);
203                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
204                                 break;
205                         }
206
207                         if ((pattrib->crc_err) || (pattrib->icv_err))
208                         {
209 #ifdef CONFIG_MP_INCLUDED
210                                 if (padapter->registrypriv.mp_mode == 1)
211                                 {
212                                         if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0))
213                                         {
214                                                 if (pattrib->crc_err == 1)
215                                                         padapter->mppriv.rx_crcerrpktcount++;
216                                         }
217                                 }
218                                 else
219 #endif
220                                 {
221                                         DBG_8192C("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err);
222                                 }
223                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
224                         }
225                         else
226                         {
227                                 //      Modified by Albert 20101213
228                                 //      For 8 bytes IP header alignment.
229                                 if (pattrib->qos)       //      Qos data, wireless lan header length is 26
230                                 {
231                                         shift_sz = 6;
232                                 }
233                                 else
234                                 {
235                                         shift_sz = 0;
236                                 }
237
238                                 skb_len = pattrib->pkt_len;
239
240                                 // for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet.
241                                 // modify alloc_sz for recvive crc error packet by thomas 2011-06-02
242                                 if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0)){
243                                         //alloc_sz = 1664;      //1664 is 128 alignment.
244                                         if(skb_len <= 1650)
245                                                 alloc_sz = 1664;
246                                         else
247                                                 alloc_sz = skb_len + 14;
248                                 }
249                                 else {
250                                         alloc_sz = skb_len;
251                                         //      6 is for IP header 8 bytes alignment in QoS packet case.
252                                         //      8 is for skb->data 4 bytes alignment.
253                                         alloc_sz += 14;
254                                 }
255
256                                 pkt_copy = rtw_skb_alloc(alloc_sz);
257
258                                 if (pkt_copy)
259                                 {
260                                         pkt_copy->dev = padapter->pnetdev;
261                                         precvframe->u.hdr.pkt = pkt_copy;
262                                         skb_reserve( pkt_copy, 8 - ((SIZE_PTR)( pkt_copy->data ) & 7 ));//force pkt_copy->data at 8-byte alignment address
263                                         skb_reserve( pkt_copy, shift_sz );//force ip_hdr at 8-byte alignment address according to shift_sz.
264                                         _rtw_memcpy(pkt_copy->data, (ptr + rx_report_sz + pattrib->shift_sz), skb_len);
265                                         precvframe->u.hdr.rx_head = pkt_copy->head;
266                                         precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_copy->data;
267                                         precvframe->u.hdr.rx_end = skb_end_pointer(pkt_copy);
268                                 }
269                                 else
270                                 {
271                                         if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0))
272                                         {
273                                                 DBG_8192C("%s: alloc_skb fail, drop frag frame\n", __FUNCTION__);
274                                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
275                                                 break;
276                                         }
277
278                                         precvframe->u.hdr.pkt = rtw_skb_clone(precvbuf->pskb);
279                                         if(precvframe->u.hdr.pkt)
280                                         {
281                                                 _pkt    *pkt_clone = precvframe->u.hdr.pkt;
282
283                                                 pkt_clone->data = ptr + rx_report_sz + pattrib->shift_sz;
284                                                 skb_reset_tail_pointer(pkt_clone);
285                                                 precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail
286                                                         = pkt_clone->data;
287                                                 precvframe->u.hdr.rx_end =      pkt_clone->data + skb_len;
288                                         }
289                                         else
290                                         {
291                                                 DBG_8192C("%s: rtw_skb_clone fail\n", __FUNCTION__);
292                                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
293                                                 break;
294                                         }
295                                 }
296
297                                 recvframe_put(precvframe, skb_len);
298                                 //recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE);
299
300                                 if (pHalData->ReceiveConfig & RCR_APPFCS)
301                                         recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
302
303                                 // move to drv info position
304                                 ptr += RXDESC_SIZE;
305
306                                 // update drv info
307                                 if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
308                                         //rtl8723s_update_bassn(padapter, pdrvinfo);
309                                         ptr += 4;
310                                 }
311
312                                 if (pattrib->pkt_rpt_type == NORMAL_RX) {
313                                         // skip the rx packet with abnormal length
314                                         if (pattrib->pkt_len < 14 || pattrib->pkt_len > 8192) { 
315                                                 DBG_8192C("skip abnormal rx packet(%d)\n", pattrib->pkt_len);
316                                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
317                                                 break;
318                                         }
319
320 #ifdef CONFIG_CONCURRENT_MODE
321                                         if (rtw_buddy_adapter_up(padapter))
322                                         {
323                                                 if (pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS) {
324                                                         DBG_8192C(FUNC_ADPT_FMT ": pre_recv_entry(precvframe) != _SUCCESS\n",
325                                                                 FUNC_ADPT_ARG(padapter->pbuddy_adapter));
326                                                 }
327                                         }
328 #endif
329                                         if (pattrib->physt)
330                                                 rtl8723b_query_rx_phy_status(precvframe, (struct phy_stat*)ptr);
331
332                                         if (rtw_recv_entry(precvframe) != _SUCCESS) {
333                                                 RT_TRACE(_module_rtl871x_recv_c_, _drv_dump_, ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n",__FUNCTION__));
334                                         }
335                                 }
336                                 else {
337 #ifdef CONFIG_C2H_PACKET_EN
338                                         if (pattrib->pkt_rpt_type == C2H_PACKET) {
339                                                 rtl8723b_c2h_packet_handler(padapter, precvframe->u.hdr.rx_data, pattrib->pkt_len);
340                                         }
341                                         else {
342                                                 DBG_8192C("%s: [WARNNING] RX type(%d) not be handled!\n",
343                                                         __FUNCTION__, pattrib->pkt_rpt_type);
344                                         }
345 #endif
346                                         rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
347                                 }
348                         }
349
350                         pkt_offset = _RND8(pkt_offset);
351                         precvbuf->pdata += pkt_offset;
352                         ptr = precvbuf->pdata;
353                         precvframe = NULL;
354                         pkt_copy = NULL;
355                 }
356
357                 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
358         } while (1);
359
360 }
361 #else
362 static void rtl8723bs_recv_tasklet(void *priv)
363 {
364         PADAPTER                                padapter;
365         PHAL_DATA_TYPE                  pHalData;
366         struct recv_priv                *precvpriv;
367         struct recv_buf                 *precvbuf;
368         union recv_frame                *precvframe;
369         struct recv_frame_hdr   *phdr;
370         struct rx_pkt_attrib    *pattrib;
371         u8                      *ptr;
372         _pkt            *ppkt;
373         u32             pkt_offset;
374         _irqL           irql;
375
376
377         padapter = (PADAPTER)priv;
378         pHalData = GET_HAL_DATA(padapter);
379         precvpriv = &padapter->recvpriv;
380
381         do {
382                 precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
383                 if (NULL == precvbuf) break;
384
385                 ptr = precvbuf->pdata;
386
387                 while (ptr < precvbuf->ptail)
388                 {
389                         precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
390                         if (precvframe == NULL) {
391                                 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("rtl8723bs_recv_tasklet: no enough recv frame!\n"));
392                                 rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
393
394                                 // The case of can't allocte recvframe should be temporary,
395                                 // schedule again and hope recvframe is available next time.
396 #ifdef PLATFORM_LINUX
397                                 tasklet_schedule(&precvpriv->recv_tasklet);
398 #endif
399                                 return;
400                         }
401
402                         phdr = &precvframe->u.hdr;
403                         pattrib = &phdr->attrib;
404
405                         rtl8723b_query_rx_desc_status(precvframe, ptr);
406
407 #if 0
408                         {
409                                 int i, len = 64;
410                                 u8 *pptr = ptr;
411
412                                 if((*(pptr + RXDESC_SIZE + pattrib->drvinfo_sz) != 0x80) && (*(pptr + RXDESC_SIZE + pattrib->drvinfo_sz) != 0x40))
413                                 {
414                                         DBG_871X("##############RxDESC############### \n");
415                                         for(i=0; i<32;i=i+16)
416                                                 DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(pptr+i),
417                                                 *(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),
418                                                  *(pptr+i+11), *(pptr+i+12), *(pptr+i+13), *(pptr+i+14), *(pptr+i+15));
419                                         
420                                         if(pattrib->pkt_len < 100)
421                                                 len = pattrib->pkt_len;
422                                         pptr = ptr + RXDESC_SIZE + pattrib->drvinfo_sz;
423                                         DBG_871X("##############Len=%d############### \n", pattrib->pkt_len);
424                                         for(i=0; i<len;i=i+16)
425                                                 DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(pptr+i),
426                                                 *(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),
427                                                  *(pptr+i+11), *(pptr+i+12), *(pptr+i+13), *(pptr+i+14), *(pptr+i+15));
428                                         DBG_871X("############################# \n");
429                                 }
430                         }
431 #endif
432
433                         // fix Hardware RX data error, drop whole recv_buffer
434                         if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err)
435                         {
436                                 DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
437                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
438                                 break;
439                         }
440
441                         pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->pkt_len;
442 #if 0 // reduce check to speed up
443                         if ((ptr + pkt_offset) > precvbuf->ptail) {
444                                 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
445                                                 ("%s: next pkt len(%p,%d) exceed ptail(%p)!\n",
446                                                 __FUNCTION__, ptr, pkt_offset, precvbuf->ptail));
447                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
448                                 break;
449                         }
450 #endif
451
452                         if ((pattrib->crc_err) || (pattrib->icv_err))
453                         {
454 #ifdef CONFIG_MP_INCLUDED
455                                 if (padapter->registrypriv.mp_mode == 1)
456                                 {
457                                         if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0))
458                                         {
459                                                 if (pattrib->crc_err == 1)
460                                                         padapter->mppriv.rx_crcerrpktcount++;
461                                         }
462                                 }
463                                 else
464 #endif
465                                 {
466                                         DBG_8192C("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err);
467                                 }
468                                 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
469                         }
470                         else
471                         {
472                                 ppkt = rtw_skb_clone(precvbuf->pskb);
473                                 if (ppkt == NULL) {
474                                         DBG_8192C("%s: no enough memory to allocate SKB!\n", __FUNCTION__);
475                                         rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
476                                         rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
477
478                                         // The case of can't allocte skb is serious and may never be recovered,
479                                         // once bDriverStopped is enable, this task should be stopped.
480                                         if (padapter->bDriverStopped == _FALSE) {
481 #ifdef PLATFORM_LINUX
482                                                 tasklet_schedule(&precvpriv->recv_tasklet);
483 #endif
484                                         }
485
486                                         return;
487                                 }
488
489                                 phdr->pkt = ppkt;
490                                 phdr->len = 0;
491                                 phdr->rx_head = precvbuf->phead;
492                                 phdr->rx_data = phdr->rx_tail = precvbuf->pdata;
493                                 phdr->rx_end = precvbuf->pend;
494                                 recvframe_put(precvframe, pkt_offset);
495                                 recvframe_pull(precvframe, RXDESC_SIZE + pattrib->drvinfo_sz);
496                                 if (pHalData->ReceiveConfig & RCR_APPFCS)
497                                         recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
498
499                                 // move to drv info position
500                                 ptr += RXDESC_SIZE;
501
502                                 // update drv info
503                                 if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
504                                         //rtl8723s_update_bassn(padapter, pdrvinfo);
505                                         ptr += 4;
506                                 }
507
508                                 if (pattrib->pkt_rpt_type == NORMAL_RX) {
509 #ifdef CONFIG_CONCURRENT_MODE
510                                         if (rtw_buddy_adapter_up(padapter))
511                                         {
512                                                 if (pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS) {
513                                                         DBG_8192C(FUNC_ADPT_FMT ": pre_recv_entry(precvframe) != _SUCCESS\n",
514                                                                 FUNC_ADPT_ARG(padapter->pbuddy_adapter));
515                                                 }
516                                         }
517 #endif
518                                         if (pattrib->physt)
519                                                 rtl8723b_query_rx_phy_status(precvframe, (struct phy_stat*)ptr);
520
521                                         if (rtw_recv_entry(precvframe) != _SUCCESS)
522                                         {
523                                                 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("rtl8723bs_recv_tasklet: rtw_recv_entry(precvframe) != _SUCCESS\n"));
524                                         }
525                                 }
526                                 else {
527 #ifdef CONFIG_C2H_PACKET_EN
528                                         if (pattrib->pkt_rpt_type == C2H_PACKET) {
529                                                 rtl8723b_c2h_packet_handler(padapter, precvframe->u.hdr.rx_data, pattrib->pkt_len);
530                                         }
531                                         else {
532                                                 DBG_8192C("%s: [WARNNING] RX type(%d) not be handled!\n",
533                                                         __FUNCTION__, pattrib->pkt_rpt_type);
534                                         }
535 #endif
536                                         rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
537                                 }
538                         }
539
540                         pkt_offset = _RND8(pkt_offset);
541                         precvbuf->pdata += pkt_offset;
542                         ptr = precvbuf->pdata;
543                 }
544
545                 rtw_skb_free(precvbuf->pskb);
546                 precvbuf->pskb = NULL;
547                 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
548         } while (1);
549 }
550 #endif
551
552 /*
553  * Initialize recv private variable for hardware dependent
554  * 1. recv buf
555  * 2. recv tasklet
556  *
557  */
558 s32 rtl8723bs_init_recv_priv(PADAPTER padapter)
559 {
560         s32                     res;
561         u32                     i, n;
562         struct recv_priv        *precvpriv;
563         struct recv_buf         *precvbuf;
564
565
566         res = _SUCCESS;
567         precvpriv = &padapter->recvpriv;
568
569         //3 1. init recv buffer
570         _rtw_init_queue(&precvpriv->free_recv_buf_queue);
571         _rtw_init_queue(&precvpriv->recv_buf_pending_queue);
572
573         n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
574         precvpriv->pallocated_recv_buf = rtw_zmalloc(n);
575         if (precvpriv->pallocated_recv_buf == NULL) {
576                 res = _FAIL;
577                 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("alloc recv_buf fail!\n"));
578                 goto exit;
579         }
580
581         precvpriv->precv_buf = (u8*)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4);
582
583         // init each recv buffer
584         precvbuf = (struct recv_buf*)precvpriv->precv_buf;
585         for (i = 0; i < NR_RECVBUFF; i++)
586         {
587                 res = initrecvbuf(precvbuf, padapter);
588                 if (res == _FAIL)
589                         break;
590
591                 res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
592                 if (res == _FAIL) {
593                         freerecvbuf(precvbuf);
594                         break;
595                 }
596
597 #ifdef CONFIG_SDIO_RX_COPY
598                 if (precvbuf->pskb == NULL) {
599                         SIZE_PTR tmpaddr=0;
600                         SIZE_PTR alignment=0;
601
602                         precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
603
604                         if(precvbuf->pskb)
605                         {
606                                 precvbuf->pskb->dev = padapter->pnetdev;
607
608                                 tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
609                                 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
610                                 skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
611                         }
612
613                         if (precvbuf->pskb == NULL) {
614                                 DBG_871X("%s: alloc_skb fail!\n", __FUNCTION__);
615                         }
616                 }
617 #endif
618
619                 rtw_list_insert_tail(&precvbuf->list, &precvpriv->free_recv_buf_queue.queue);
620
621                 precvbuf++;
622         }
623         precvpriv->free_recv_buf_queue_cnt = i;
624
625         if (res == _FAIL)
626                 goto initbuferror;
627
628         //3 2. init tasklet
629 #ifdef PLATFORM_LINUX
630         tasklet_init(&precvpriv->recv_tasklet,
631              (void(*)(unsigned long))rtl8723bs_recv_tasklet,
632              (unsigned long)padapter);
633 #endif
634
635         goto exit;
636
637 initbuferror:
638         precvbuf = (struct recv_buf*)precvpriv->precv_buf;
639         if (precvbuf) {
640                 n = precvpriv->free_recv_buf_queue_cnt;
641                 precvpriv->free_recv_buf_queue_cnt = 0;
642                 for (i = 0; i < n ; i++)
643                 {
644                         rtw_list_delete(&precvbuf->list);
645                         rtw_os_recvbuf_resource_free(padapter, precvbuf);
646                         freerecvbuf(precvbuf);
647                         precvbuf++;
648                 }
649                 precvpriv->precv_buf = NULL;
650         }
651
652         if (precvpriv->pallocated_recv_buf) {
653                 n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
654                 rtw_mfree(precvpriv->pallocated_recv_buf, n);
655                 precvpriv->pallocated_recv_buf = NULL;
656         }
657
658 exit:
659         return res;
660 }
661
662 /*
663  * Free recv private variable of hardware dependent
664  * 1. recv buf
665  * 2. recv tasklet
666  *
667  */
668 void rtl8723bs_free_recv_priv(PADAPTER padapter)
669 {
670         u32                     i, n;
671         struct recv_priv        *precvpriv;
672         struct recv_buf         *precvbuf;
673
674
675         precvpriv = &padapter->recvpriv;
676
677         //3 1. kill tasklet
678 #ifdef PLATFORM_LINUX
679         tasklet_kill(&precvpriv->recv_tasklet);
680 #endif
681
682         //3 2. free all recv buffers
683         precvbuf = (struct recv_buf*)precvpriv->precv_buf;
684         if (precvbuf) {
685                 n = NR_RECVBUFF;
686                 precvpriv->free_recv_buf_queue_cnt = 0;
687                 for (i = 0; i < n ; i++)
688                 {
689                         rtw_list_delete(&precvbuf->list);
690                         rtw_os_recvbuf_resource_free(padapter, precvbuf);
691                         freerecvbuf(precvbuf);
692                         precvbuf++;
693                 }
694                 precvpriv->precv_buf = NULL;
695         }
696
697         if (precvpriv->pallocated_recv_buf) {
698                 n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
699                 rtw_mfree(precvpriv->pallocated_recv_buf, n);
700                 precvpriv->pallocated_recv_buf = NULL;
701         }
702 }
703