1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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.
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
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
19 ******************************************************************************/
20 #define _RTL8723AS_RECV_C_
24 #if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS)
25 #error "Shall be Linux or Windows, but not both!\n"
28 #include <drv_types.h>
29 #include <recv_osdep.h>
30 #include <rtl8723a_hal.h>
34 static s32 initrecvbuf(struct recv_buf *precvbuf, PADAPTER padapter)
36 _rtw_init_listhead(&precvbuf->list);
37 _rtw_spinlock_init(&precvbuf->recvbuf_lock);
39 precvbuf->adapter = padapter;
44 static void freerecvbuf(struct recv_buf *precvbuf)
46 _rtw_spinlock_free(&precvbuf->recvbuf_lock);
49 static void update_recvframe_attrib(
50 union recv_frame *precvframe,
51 struct recv_stat *prxstat)
53 struct rx_pkt_attrib *pattrib;
54 struct recv_stat report;
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);
65 prxreport = (PRXREPORT)&report;
67 pattrib = &precvframe->u.hdr.attrib;
68 _rtw_memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
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;
75 pattrib->crc_err = (u8)prxreport->crc32;
76 pattrib->icv_err = (u8)prxreport->icverr;
78 pattrib->bdecrypted = (u8)(prxreport->swdec ? 0 : 1);
79 pattrib->encrypt = (u8)prxreport->security;
81 pattrib->qos = (u8)prxreport->qos;
82 pattrib->priority = (u8)prxreport->tid;
84 pattrib->amsdu = (u8)prxreport->amsdu;
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;
91 pattrib->mcs_rate = (u8)prxreport->rxmcs;
92 pattrib->rxht = (u8)prxreport->rxht;
97 * Before calling this function,
98 * precvframe->u.hdr.rx_data should be ready!
100 void update_recvframe_phyinfo(
101 union recv_frame *precvframe,
102 struct phy_stat *pphy_status)
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);
110 ODM_PACKET_INFO_T pkt_info;
113 struct sta_priv *pstapriv;
114 struct sta_info *psta;
116 pkt_info.bPacketMatchBSSID =_FALSE;
117 pkt_info.bPacketToSelf = _FALSE;
118 pkt_info.bPacketBeacon = _FALSE;
121 wlanhdr = get_recvframe_data(precvframe);
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));
127 pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID && (_rtw_memcmp(get_da(wlanhdr), myid(&padapter->eeprompriv), ETH_ALEN));
129 pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID && (GetFrameSubType(wlanhdr) == WIFI_BEACON);
131 if(pkt_info.bPacketBeacon){
132 if(check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _TRUE){
133 sa = padapter->mlmepriv.cur_network.network.MacAddress;
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]);
144 sa = get_sa(wlanhdr);
147 pkt_info.StationID = 0xFF;
149 pstapriv = &padapter->stapriv;
150 psta = rtw_get_stainfo(pstapriv, sa);
153 pkt_info.StationID = psta->mac_id;
154 //DBG_8192C("%s ==> StationID(%d)\n",__FUNCTION__,pkt_info.StationID);
156 pkt_info.Rate = pattrib->mcs_rate;
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))
169 precvframe->u.hdr.psta = psta;
170 rtl8192c_process_phy_info(padapter, precvframe);
173 else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon)
175 if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == _TRUE)
179 precvframe->u.hdr.psta = psta;
182 rtl8192c_process_phy_info(padapter, precvframe);
186 static s32 pre_recv_entry(union recv_frame *precvframe, struct recv_buf *precvbuf, struct phy_stat *pphy_status)
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);
198 if(!secondary_padapter)
201 paddr1 = GetAddr1Ptr(precvframe->u.hdr.rx_data);
203 if(IS_MCAST(paddr1) == _FALSE)//unicast packets
205 //primary_myid = myid(&primary_padapter->eeprompriv);
206 secondary_myid = myid(&secondary_padapter->eeprompriv);
208 if(_rtw_memcmp(paddr1, secondary_myid, ETH_ALEN))
210 //change to secondary interface
211 precvframe->u.hdr.adapter = secondary_padapter;
214 //ret = recv_entry(precvframe);
217 else // Handle BC/MC Packets
220 _pkt *pkt_copy = NULL;
221 struct rx_pkt_attrib *pattrib = NULL;
223 precvframe_if2 = rtw_alloc_recvframe(pfree_recv_queue);
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;
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);
236 pkt_copy = rtw_skb_copy(precvframe->u.hdr.pkt);
237 if (pkt_copy == NULL)
239 if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0))
241 DBG_8192C("pre_recv_entry(): rtw_skb_copy fail , drop frag frame \n");
242 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
246 pkt_copy = rtw_skb_clone(precvframe->u.hdr.pkt);
249 DBG_8192C("pre_recv_entry(): rtw_skb_clone fail , drop frame\n");
250 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
255 pkt_copy->dev = secondary_padapter->pnetdev;
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;
264 //recvframe_put(precvframe_if2, pattrib->pkt_len);
266 if ( pHalData->ReceiveConfig & RCR_APPFCS)
267 recvframe_pull_tail(precvframe_if2, IEEE80211_FCS_LEN);
270 update_recvframe_phyinfo(precvframe_if2, pphy_status);
272 if(rtw_recv_entry(precvframe_if2) != _SUCCESS)
274 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
275 ("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n"));
279 if (precvframe->u.hdr.attrib.physt)
280 update_recvframe_phyinfo(precvframe, pphy_status);
282 ret = rtw_recv_entry(precvframe);
290 #ifdef CONFIG_SDIO_RX_COPY
291 #ifdef CONFIG_DIRECT_RECV
292 void rtl8723as_recv(PADAPTER padapter, struct recv_buf *precvbuf)
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;
303 u32 pkt_len, pkt_offset, skb_len, alloc_sz;
304 _pkt *pkt_copy = NULL;
305 u8 shift_sz = 0, rx_report_sz = 0;
307 pHalData = GET_HAL_DATA(padapter);
308 precvpriv = &padapter->recvpriv;
310 ptr = precvbuf->pdata;
312 while (ptr < precvbuf->ptail)
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__));
321 update_recvframe_attrib(precvframe, (struct recv_stat*)ptr);
323 pattrib = &precvframe->u.hdr.attrib;
325 // fix Hardware RX data error, drop whole recv_buffer
326 if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err)
328 DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
330 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
334 if (pHalData->ReceiveConfig & RCR_APP_BA_SSN)
335 rx_report_sz = RXDESC_SIZE + 4 + pattrib->drvinfo_sz;
337 rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz;
339 pkt_offset = rx_report_sz + pattrib->pkt_len;
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);
347 if ((pattrib->crc_err) || (pattrib->icv_err))
349 #ifdef CONFIG_MP_INCLUDED
350 if (padapter->registrypriv.mp_mode == 1)
352 if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0))
354 if (pattrib->crc_err == 1)
355 padapter->mppriv.rx_crcerrpktcount++;
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);
364 // Modified by Albert 20101213
365 // For 8 bytes IP header alignment.
366 if (pattrib->qos) // Qos data, wireless lan header length is 26
375 skb_len = pattrib->pkt_len;
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.
384 alloc_sz = skb_len + 14;
388 // 6 is for IP header 8 bytes alignment in QoS packet case.
389 // 8 is for skb->data 4 bytes alignment.
393 pkt_copy = rtw_skb_alloc(alloc_sz);
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);
408 if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0))
410 DBG_8192C("rtl8723as_recv_tasklet: alloc_skb fail , drop frag frame \n");
411 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
415 precvframe->u.hdr.pkt = rtw_skb_clone(precvbuf->pskb);
416 if(precvframe->u.hdr.pkt)
418 _pkt *pkt_clone = precvframe->u.hdr.pkt;
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
424 precvframe->u.hdr.rx_end = pkt_clone->data + skb_len;
428 DBG_8192C("rtl8723as_recv_tasklet: rtw_skb_clone fail\n");
429 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
434 recvframe_put(precvframe, skb_len);
435 //recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE);
437 if (pHalData->ReceiveConfig & RCR_APPFCS)
438 recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
440 // move to drv info position
444 if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
445 //rtl8723s_update_bassn(padapter, pdrvinfo);
449 #ifdef CONFIG_CONCURRENT_MODE
450 if(rtw_buddy_adapter_up(padapter))
452 if(pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS)
454 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
455 ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n"));
462 update_recvframe_phyinfo(precvframe, (struct phy_stat*)ptr);
464 if (rtw_recv_entry(precvframe) != _SUCCESS)
466 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n",__FUNCTION__));
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;
481 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
484 #endif //CONFIG_DIRECT_RECV
486 static void rtl8723as_recv_tasklet(void *priv)
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;
497 u32 pkt_len, pkt_offset, skb_len, alloc_sz;
498 _pkt *pkt_copy = NULL;
499 u8 shift_sz = 0, rx_report_sz = 0;
502 padapter = (PADAPTER)priv;
503 pHalData = GET_HAL_DATA(padapter);
504 precvpriv = &padapter->recvpriv;
507 precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
508 if (NULL == precvbuf) break;
510 ptr = precvbuf->pdata;
512 while (ptr < precvbuf->ptail)
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);
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);
528 update_recvframe_attrib(precvframe, (struct recv_stat*)ptr);
530 pattrib = &precvframe->u.hdr.attrib;
532 // fix Hardware RX data error, drop whole recv_buffer
533 if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err)
535 DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
537 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
541 if (pHalData->ReceiveConfig & RCR_APP_BA_SSN)
542 rx_report_sz = RXDESC_SIZE + 4 + pattrib->drvinfo_sz;
544 rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz;
546 pkt_offset = rx_report_sz + pattrib->pkt_len;
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);
554 if ((pattrib->crc_err) || (pattrib->icv_err))
556 #ifdef CONFIG_MP_INCLUDED
557 if (padapter->registrypriv.mp_mode == 1)
559 if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0))
561 if (pattrib->crc_err == 1)
562 padapter->mppriv.rx_crcerrpktcount++;
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);
571 // Modified by Albert 20101213
572 // For 8 bytes IP header alignment.
573 if (pattrib->qos) // Qos data, wireless lan header length is 26
582 skb_len = pattrib->pkt_len;
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.
591 alloc_sz = skb_len + 14;
595 // 6 is for IP header 8 bytes alignment in QoS packet case.
596 // 8 is for skb->data 4 bytes alignment.
600 pkt_copy = rtw_skb_alloc(alloc_sz);
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);
615 if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0))
617 DBG_8192C("rtl8723as_recv_tasklet: alloc_skb fail , drop frag frame \n");
618 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
622 precvframe->u.hdr.pkt = rtw_skb_clone(precvbuf->pskb);
623 if(precvframe->u.hdr.pkt)
625 _pkt *pkt_clone = precvframe->u.hdr.pkt;
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
631 precvframe->u.hdr.rx_end = pkt_clone->data + skb_len;
635 DBG_8192C("rtl8723as_recv_tasklet: rtw_skb_clone fail\n");
636 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
641 recvframe_put(precvframe, skb_len);
642 //recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE);
644 if (pHalData->ReceiveConfig & RCR_APPFCS)
645 recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
647 // move to drv info position
651 if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
652 //rtl8723s_update_bassn(padapter, pdrvinfo);
656 #ifdef CONFIG_CONCURRENT_MODE
657 if(rtw_buddy_adapter_up(padapter))
659 if(pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS)
661 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
662 ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n"));
669 update_recvframe_phyinfo(precvframe, (struct phy_stat*)ptr);
671 if (rtw_recv_entry(precvframe) != _SUCCESS)
673 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n",__FUNCTION__));
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;
687 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
692 static void rtl8723as_recv_tasklet(void *priv)
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;
707 padapter = (PADAPTER)priv;
708 pHalData = GET_HAL_DATA(padapter);
709 precvpriv = &padapter->recvpriv;
712 precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
713 if (NULL == precvbuf) break;
715 ptr = precvbuf->pdata;
717 while (ptr < precvbuf->ptail)
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);
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);
732 phdr = &precvframe->u.hdr;
733 pattrib = &phdr->attrib;
735 update_recvframe_attrib(precvframe, (struct recv_stat*)ptr);
737 // fix Hardware RX data error, drop whole recv_buffer
738 if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err)
740 DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
741 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
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);
756 if ((pattrib->crc_err) || (pattrib->icv_err))
758 #ifdef CONFIG_MP_INCLUDED
759 if (padapter->registrypriv.mp_mode == 1)
761 if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0))
763 if (pattrib->crc_err == 1)
764 padapter->mppriv.rx_crcerrpktcount++;
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);
773 ppkt = rtw_skb_clone(precvbuf->pskb);
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);
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);
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);
801 // move to drv info position
805 if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
806 // rtl8723s_update_bassn(padapter, pdrvinfo);
810 #ifdef CONFIG_CONCURRENT_MODE
811 if(rtw_buddy_adapter_up(padapter))
813 if(pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS)
815 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
816 ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n"));
823 update_recvframe_phyinfo(precvframe, (struct phy_stat*)ptr);
825 if (rtw_recv_entry(precvframe) != _SUCCESS)
827 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("rtl8723as_recv_tasklet: rtw_recv_entry(precvframe) != _SUCCESS\n"));
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;
839 rtw_skb_free(precvbuf->pskb);
840 precvbuf->pskb = NULL;
841 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
847 * Initialize recv private variable for hardware dependent
852 s32 rtl8723as_init_recv_priv(PADAPTER padapter)
856 struct recv_priv *precvpriv;
857 struct recv_buf *precvbuf;
861 precvpriv = &padapter->recvpriv;
863 //3 1. init recv buffer
864 _rtw_init_queue(&precvpriv->free_recv_buf_queue);
865 _rtw_init_queue(&precvpriv->recv_buf_pending_queue);
867 n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
868 precvpriv->pallocated_recv_buf = rtw_zmalloc(n);
869 if (precvpriv->pallocated_recv_buf == NULL) {
871 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("alloc recv_buf fail!\n"));
875 precvpriv->precv_buf = (u8*)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4);
877 // init each recv buffer
878 precvbuf = (struct recv_buf*)precvpriv->precv_buf;
879 for (i = 0; i < NR_RECVBUFF; i++)
881 res = initrecvbuf(precvbuf, padapter);
885 res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
887 freerecvbuf(precvbuf);
891 #ifdef CONFIG_SDIO_RX_COPY
892 if (precvbuf->pskb == NULL) {
894 SIZE_PTR alignment=0;
896 precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
900 precvbuf->pskb->dev = padapter->pnetdev;
902 tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
903 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
904 skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
907 if (precvbuf->pskb == NULL) {
908 DBG_871X("%s: alloc_skb fail!\n", __FUNCTION__);
913 rtw_list_insert_tail(&precvbuf->list, &precvpriv->free_recv_buf_queue.queue);
917 precvpriv->free_recv_buf_queue_cnt = i;
923 #ifdef PLATFORM_LINUX
924 tasklet_init(&precvpriv->recv_tasklet,
925 (void(*)(unsigned long))rtl8723as_recv_tasklet,
926 (unsigned long)padapter);
932 precvbuf = (struct recv_buf*)precvpriv->precv_buf;
934 n = precvpriv->free_recv_buf_queue_cnt;
935 precvpriv->free_recv_buf_queue_cnt = 0;
936 for (i = 0; i < n ; i++)
938 rtw_list_delete(&precvbuf->list);
939 rtw_os_recvbuf_resource_free(padapter, precvbuf);
940 freerecvbuf(precvbuf);
943 precvpriv->precv_buf = NULL;
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;
957 * Free recv private variable of hardware dependent
962 void rtl8723as_free_recv_priv(PADAPTER padapter)
965 struct recv_priv *precvpriv;
966 struct recv_buf *precvbuf;
969 precvpriv = &padapter->recvpriv;
972 #ifdef PLATFORM_LINUX
973 tasklet_kill(&precvpriv->recv_tasklet);
976 //3 2. free all recv buffers
977 precvbuf = (struct recv_buf*)precvpriv->precv_buf;
980 precvpriv->free_recv_buf_queue_cnt = 0;
981 for (i = 0; i < n ; i++)
983 rtw_list_delete(&precvbuf->list);
984 rtw_os_recvbuf_resource_free(padapter, precvbuf);
985 freerecvbuf(precvbuf);
988 precvpriv->precv_buf = NULL;
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;