1 /******************************************************************************
3 * Copyright(c) 2007 - 2012 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 _RTL8723BS_RECV_C_
22 #include <rtl8723b_hal.h>
25 static s32 initrecvbuf(struct recv_buf *precvbuf, PADAPTER padapter)
27 _rtw_init_listhead(&precvbuf->list);
28 _rtw_spinlock_init(&precvbuf->recvbuf_lock);
30 precvbuf->adapter = padapter;
35 static void freerecvbuf(struct recv_buf *precvbuf)
37 _rtw_spinlock_free(&precvbuf->recvbuf_lock);
40 static void update_recvframe_attrib(
42 union recv_frame *precvframe,
43 struct recv_stat *prxstat)
45 struct rx_pkt_attrib *pattrib;
46 struct recv_stat report;
47 PRXREPORT prxreport = (PRXREPORT)&report;
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);
56 pattrib = &precvframe->u.hdr.attrib;
57 _rtw_memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
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);
63 if (pattrib->pkt_rpt_type == NORMAL_RX)
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;
71 pattrib->crc_err = (u8)prxreport->crc32;
72 pattrib->icv_err = (u8)prxreport->icverr;
74 pattrib->bdecrypted = (u8)(prxreport->swdec ? 0 : 1);
75 pattrib->encrypt = (u8)prxreport->security;
77 pattrib->qos = (u8)prxreport->qos;
78 pattrib->priority = (u8)prxreport->tid;
80 pattrib->amsdu = (u8)prxreport->amsdu;
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;
87 pattrib->data_rate = (u8)prxreport->rx_rate;
91 pattrib->pkt_len = (u16)prxreport->pktlen;
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.DataRate = pattrib->data_rate;
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))
168 precvframe->u.hdr.psta = psta;
169 rtl8723b_process_phy_info(padapter, precvframe);
172 else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon)
174 if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == _TRUE)
178 precvframe->u.hdr.psta = psta;
181 rtl8723b_process_phy_info(padapter, precvframe);
185 static s32 pre_recv_entry(union recv_frame *precvframe, struct recv_buf *precvbuf, struct phy_stat *pphy_status)
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);
197 if(!secondary_padapter)
200 paddr1 = GetAddr1Ptr(precvframe->u.hdr.rx_data);
202 if(IS_MCAST(paddr1) == _FALSE)//unicast packets
204 //primary_myid = myid(&primary_padapter->eeprompriv);
205 secondary_myid = myid(&secondary_padapter->eeprompriv);
207 if(_rtw_memcmp(paddr1, secondary_myid, ETH_ALEN))
209 //change to secondary interface
210 precvframe->u.hdr.adapter = secondary_padapter;
213 //ret = recv_entry(precvframe);
216 else // Handle BC/MC Packets
219 _pkt *pkt_copy = NULL;
220 struct rx_pkt_attrib *pattrib = NULL;
222 precvframe_if2 = rtw_alloc_recvframe(pfree_recv_queue);
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;
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);
235 pkt_copy = rtw_skb_copy( precvframe->u.hdr.pkt);
236 if (pkt_copy == NULL)
238 if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0))
240 DBG_8192C("pre_recv_entry(): rtw_skb_copy fail , drop frag frame \n");
241 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
245 pkt_copy = rtw_skb_clone( precvframe->u.hdr.pkt);
248 DBG_8192C("pre_recv_entry(): rtw_skb_clone fail , drop frame\n");
249 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
254 pkt_copy->dev = secondary_padapter->pnetdev;
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;
263 //recvframe_put(precvframe_if2, pattrib->pkt_len);
265 if ( pHalData->ReceiveConfig & RCR_APPFCS)
266 recvframe_pull_tail(precvframe_if2, IEEE80211_FCS_LEN);
269 update_recvframe_phyinfo(precvframe_if2, pphy_status);
271 if(rtw_recv_entry(precvframe_if2) != _SUCCESS)
273 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
274 ("recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS\n"));
278 if (precvframe->u.hdr.attrib.physt)
279 update_recvframe_phyinfo(precvframe, pphy_status);
281 ret = rtw_recv_entry(precvframe);
288 #ifdef CONFIG_C2H_PACKET_EN
289 static void rtl8723bs_c2h_packet_handler(PADAPTER padapter, u8 *pbuf, u16 length)
297 DBG_871X("+%s() length=%d\n", __func__, length);
299 tmpBuf = rtw_zmalloc(length);
303 _rtw_memcpy(tmpBuf, pbuf, length);
305 res = rtw_c2h_packet_wk_cmd(padapter, tmpBuf, length);
307 if (res == _FALSE && tmpBuf != NULL)
308 rtw_mfree(tmpBuf, length);
310 DBG_871X("-%s res(%d)\n", __func__, res);
317 #ifdef CONFIG_SDIO_RX_COPY
318 static void rtl8723bs_recv_tasklet(void *priv)
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;
329 u32 pkt_len, pkt_offset, skb_len, alloc_sz;
330 _pkt *pkt_copy = NULL;
331 u8 shift_sz = 0, rx_report_sz = 0;
334 padapter = (PADAPTER)priv;
335 pHalData = GET_HAL_DATA(padapter);
336 precvpriv = &padapter->recvpriv;
339 precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
340 if (NULL == precvbuf) break;
342 ptr = precvbuf->pdata;
344 while (ptr < precvbuf->ptail)
346 precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
347 if (precvframe == NULL)
349 DBG_8192C("%s: no enough recv frame!\n", __FUNCTION__);
350 rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
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);
361 update_recvframe_attrib(padapter, precvframe, (struct recv_stat*)ptr);
363 pattrib = &precvframe->u.hdr.attrib;
365 // fix Hardware RX data error, drop whole recv_buffer
366 if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err)
369 DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
371 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
375 rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz;
376 pkt_offset = rx_report_sz + pattrib->shift_sz + pattrib->pkt_len;
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);
384 if ((pattrib->crc_err) || (pattrib->icv_err))
386 #ifdef CONFIG_MP_INCLUDED
387 if (padapter->registrypriv.mp_mode == 1)
389 if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0))
391 if (pattrib->crc_err == 1)
392 padapter->mppriv.rx_crcerrpktcount++;
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);
401 // Modified by Albert 20101213
402 // For 8 bytes IP header alignment.
403 if (pattrib->qos) // Qos data, wireless lan header length is 26
412 skb_len = pattrib->pkt_len;
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.
421 alloc_sz = skb_len + 14;
425 // 6 is for IP header 8 bytes alignment in QoS packet case.
426 // 8 is for skb->data 4 bytes alignment.
430 pkt_copy = rtw_skb_alloc(alloc_sz);
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);
445 if((pattrib->mfrag == 1)&&(pattrib->frag_num == 0))
447 DBG_8192C("%s: alloc_skb fail, drop frag frame\n", __FUNCTION__);
448 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
452 precvframe->u.hdr.pkt = rtw_skb_clone(precvbuf->pskb);
453 if(precvframe->u.hdr.pkt)
455 _pkt *pkt_clone = precvframe->u.hdr.pkt;
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
461 precvframe->u.hdr.rx_end = pkt_clone->data + skb_len;
465 DBG_8192C("%s: rtw_skb_clone fail\n", __FUNCTION__);
466 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
471 recvframe_put(precvframe, skb_len);
472 //recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE);
474 if (pHalData->ReceiveConfig & RCR_APPFCS)
475 recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
477 // move to drv info position
481 if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
482 //rtl8723s_update_bassn(padapter, pdrvinfo);
486 #ifdef CONFIG_C2H_PACKET_EN
487 if(pattrib->pkt_rpt_type == NORMAL_RX)//Normal rx packet
490 #ifdef CONFIG_CONCURRENT_MODE
491 if(rtw_buddy_adapter_up(padapter))
493 if(pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS)
495 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
496 ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n"));
503 update_recvframe_phyinfo(precvframe, (struct phy_stat*)ptr);
505 if (rtw_recv_entry(precvframe) != _SUCCESS)
507 RT_TRACE(_module_rtl871x_recv_c_, _drv_dump_, ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n",__FUNCTION__));
510 #ifdef CONFIG_C2H_PACKET_EN
512 else if(pattrib->pkt_rpt_type == C2H_PACKET)
514 C2H_EVT_HDR C2hEvent;
516 u16 len_c2h = pattrib->pkt_len;
517 u8 *pbuf_c2h = precvframe->u.hdr.rx_data;
520 C2hEvent.CmdID = pbuf_c2h[0];
521 C2hEvent.CmdSeq = pbuf_c2h[1];
522 C2hEvent.CmdLen = (len_c2h -2);
523 pdata_c2h = pbuf_c2h+2;
525 if(C2hEvent.CmdID == C2H_CCX_TX_RPT)
527 CCX_FwC2HTxRpt_8723b(padapter, pdata_c2h, C2hEvent.CmdLen);
531 rtl8723bs_c2h_packet_handler(padapter, precvframe->u.hdr.rx_data, pattrib->pkt_len);
534 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
540 pkt_offset = _RND8(pkt_offset);
541 precvbuf->pdata += pkt_offset;
542 ptr = precvbuf->pdata;
547 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
552 static void rtl8723bs_recv_tasklet(void *priv)
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;
567 padapter = (PADAPTER)priv;
568 pHalData = GET_HAL_DATA(padapter);
569 precvpriv = &padapter->recvpriv;
572 precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
573 if (NULL == precvbuf) break;
575 ptr = precvbuf->pdata;
577 while (ptr < precvbuf->ptail)
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);
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);
592 phdr = &precvframe->u.hdr;
593 pattrib = &phdr->attrib;
595 update_recvframe_attrib(padapter, precvframe, (struct recv_stat*)ptr);
602 if((*(pptr + RXDESC_SIZE + pattrib->drvinfo_sz) != 0x80) && (*(pptr + RXDESC_SIZE + pattrib->drvinfo_sz) != 0x40))
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));
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");
623 // fix Hardware RX data error, drop whole recv_buffer
624 if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err)
626 DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
627 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
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);
642 if ((pattrib->crc_err) || (pattrib->icv_err))
644 #ifdef CONFIG_MP_INCLUDED
645 if (padapter->registrypriv.mp_mode == 1)
647 if ((check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0))
649 if (pattrib->crc_err == 1)
650 padapter->mppriv.rx_crcerrpktcount++;
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);
659 ppkt = rtw_skb_clone(precvbuf->pskb);
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);
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);
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);
687 // move to drv info position
691 if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
692 // rtl8723s_update_bassn(padapter, pdrvinfo);
696 if(pattrib->pkt_rpt_type == NORMAL_RX)//Normal rx packet
698 #ifdef CONFIG_CONCURRENT_MODE
699 if(rtw_buddy_adapter_up(padapter))
701 if(pre_recv_entry(precvframe, precvbuf, (struct phy_stat*)ptr) != _SUCCESS)
703 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,
704 ("recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS\n"));
711 update_recvframe_phyinfo(precvframe, (struct phy_stat*)ptr);
713 if (rtw_recv_entry(precvframe) != _SUCCESS)
715 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("rtl8723bs_recv_tasklet: rtw_recv_entry(precvframe) != _SUCCESS\n"));
719 #ifdef CONFIG_C2H_PACKET_EN
720 else if(pattrib->pkt_rpt_type == C2H_PACKET)
722 rtl8723bs_c2h_packet_handler(padapter, precvframe->u.hdr.rx_data, pattrib->pkt_len);
723 rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
728 pkt_offset = _RND8(pkt_offset);
729 precvbuf->pdata += pkt_offset;
730 ptr = precvbuf->pdata;
733 rtw_skb_free(precvbuf->pskb);
734 precvbuf->pskb = NULL;
735 rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
741 * Initialize recv private variable for hardware dependent
746 s32 rtl8723bs_init_recv_priv(PADAPTER padapter)
750 struct recv_priv *precvpriv;
751 struct recv_buf *precvbuf;
755 precvpriv = &padapter->recvpriv;
757 //3 1. init recv buffer
758 _rtw_init_queue(&precvpriv->free_recv_buf_queue);
759 _rtw_init_queue(&precvpriv->recv_buf_pending_queue);
761 n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
762 precvpriv->pallocated_recv_buf = rtw_zmalloc(n);
763 if (precvpriv->pallocated_recv_buf == NULL) {
765 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("alloc recv_buf fail!\n"));
769 precvpriv->precv_buf = (u8*)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4);
771 // init each recv buffer
772 precvbuf = (struct recv_buf*)precvpriv->precv_buf;
773 for (i = 0; i < NR_RECVBUFF; i++)
775 res = initrecvbuf(precvbuf, padapter);
779 res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
781 freerecvbuf(precvbuf);
785 #ifdef CONFIG_SDIO_RX_COPY
786 if (precvbuf->pskb == NULL) {
788 SIZE_PTR alignment=0;
790 precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
794 precvbuf->pskb->dev = padapter->pnetdev;
796 tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
797 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
798 skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
801 if (precvbuf->pskb == NULL) {
802 DBG_871X("%s: alloc_skb fail!\n", __FUNCTION__);
807 rtw_list_insert_tail(&precvbuf->list, &precvpriv->free_recv_buf_queue.queue);
811 precvpriv->free_recv_buf_queue_cnt = i;
817 #ifdef PLATFORM_LINUX
818 tasklet_init(&precvpriv->recv_tasklet,
819 (void(*)(unsigned long))rtl8723bs_recv_tasklet,
820 (unsigned long)padapter);
826 precvbuf = (struct recv_buf*)precvpriv->precv_buf;
828 n = precvpriv->free_recv_buf_queue_cnt;
829 precvpriv->free_recv_buf_queue_cnt = 0;
830 for (i = 0; i < n ; i++)
832 rtw_list_delete(&precvbuf->list);
833 rtw_os_recvbuf_resource_free(padapter, precvbuf);
834 freerecvbuf(precvbuf);
837 precvpriv->precv_buf = NULL;
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;
851 * Free recv private variable of hardware dependent
856 void rtl8723bs_free_recv_priv(PADAPTER padapter)
859 struct recv_priv *precvpriv;
860 struct recv_buf *precvbuf;
863 precvpriv = &padapter->recvpriv;
866 #ifdef PLATFORM_LINUX
867 tasklet_kill(&precvpriv->recv_tasklet);
870 //3 2. free all recv buffers
871 precvbuf = (struct recv_buf*)precvpriv->precv_buf;
874 precvpriv->free_recv_buf_queue_cnt = 0;
875 for (i = 0; i < n ; i++)
877 rtw_list_delete(&precvbuf->list);
878 rtw_os_recvbuf_resource_free(padapter, precvbuf);
879 freerecvbuf(precvbuf);
882 precvpriv->precv_buf = NULL;
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;