Path: blob/master/ALFA-W1F1/RTL8814AU/core/rtw_recv.c
1307 views
/******************************************************************************1*2* Copyright(c) 2007 - 2017 Realtek Corporation.3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of version 2 of the GNU General Public License as6* published by the Free Software Foundation.7*8* This program is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for11* more details.12*13*****************************************************************************/14#define _RTW_RECV_C_1516#include <drv_types.h>17#include <hal_data.h>1819#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS20static void rtw_signal_stat_timer_hdl(void *ctx);2122enum {23SIGNAL_STAT_CALC_PROFILE_0 = 0,24SIGNAL_STAT_CALC_PROFILE_1,25SIGNAL_STAT_CALC_PROFILE_MAX26};2728u8 signal_stat_calc_profile[SIGNAL_STAT_CALC_PROFILE_MAX][2] = {29{4, 1}, /* Profile 0 => pre_stat : curr_stat = 4 : 1 */30{3, 7} /* Profile 1 => pre_stat : curr_stat = 3 : 7 */31};3233#ifndef RTW_SIGNAL_STATE_CALC_PROFILE34#define RTW_SIGNAL_STATE_CALC_PROFILE SIGNAL_STAT_CALC_PROFILE_135#endif3637#endif /* CONFIG_NEW_SIGNAL_STAT_PROCESS */3839u8 rtw_bridge_tunnel_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };40u8 rtw_rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };41static u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37};42static u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3};43#ifdef CONFIG_TDLS44static u8 SNAP_ETH_TYPE_TDLS[2] = {0x89, 0x0d};45#endif4647#ifdef CONFIG_CUSTOMER_ALIBABA_GENERAL48int recv_frame_monitor(_adapter *padapter, union recv_frame *rframe);49#endif50void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv)51{52535455_rtw_memset((u8 *)psta_recvpriv, 0, sizeof(struct sta_recv_priv));5657_rtw_spinlock_init(&psta_recvpriv->lock);5859/* for(i=0; i<MAX_RX_NUMBLKS; i++) */60/* _rtw_init_queue(&psta_recvpriv->blk_strms[i]); */6162_rtw_init_queue(&psta_recvpriv->defrag_q);636465}6667sint _rtw_init_recv_priv(struct recv_priv *precvpriv, _adapter *padapter)68{69sint i;7071union recv_frame *precvframe;72sint res = _SUCCESS;737475/* We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc(). */76/* _rtw_memset((unsigned char *)precvpriv, 0, sizeof (struct recv_priv)); */7778_rtw_spinlock_init(&precvpriv->lock);7980#ifdef CONFIG_RECV_THREAD_MODE81_rtw_init_sema(&precvpriv->recv_sema, 0);8283#endif8485_rtw_init_queue(&precvpriv->free_recv_queue);86_rtw_init_queue(&precvpriv->recv_pending_queue);87_rtw_init_queue(&precvpriv->uc_swdec_pending_queue);8889precvpriv->adapter = padapter;9091precvpriv->free_recvframe_cnt = NR_RECVFRAME;9293precvpriv->sink_udpport = 0;94precvpriv->pre_rtp_rxseq = 0;95precvpriv->cur_rtp_rxseq = 0;9697#ifdef DBG_RX_SIGNAL_DISPLAY_RAW_DATA98precvpriv->store_law_data_flag = 1;99#else100precvpriv->store_law_data_flag = 0;101#endif102103rtw_os_recv_resource_init(precvpriv, padapter);104105precvpriv->pallocated_frame_buf = rtw_zvmalloc(NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);106107if (precvpriv->pallocated_frame_buf == NULL) {108res = _FAIL;109goto exit;110}111/* _rtw_memset(precvpriv->pallocated_frame_buf, 0, NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ); */112113precvpriv->precv_frame_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_frame_buf), RXFRAME_ALIGN_SZ);114/* precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf + RXFRAME_ALIGN_SZ - */115/* ((SIZE_PTR) (precvpriv->pallocated_frame_buf) &(RXFRAME_ALIGN_SZ-1)); */116117precvframe = (union recv_frame *) precvpriv->precv_frame_buf;118119120for (i = 0; i < NR_RECVFRAME ; i++) {121_rtw_init_listhead(&(precvframe->u.list));122123rtw_list_insert_tail(&(precvframe->u.list), &(precvpriv->free_recv_queue.queue));124125rtw_os_recv_resource_alloc(padapter, precvframe);126127precvframe->u.hdr.len = 0;128129precvframe->u.hdr.adapter = padapter;130precvframe++;131132}133134#ifdef CONFIG_USB_HCI135136ATOMIC_SET(&(precvpriv->rx_pending_cnt), 1);137138_rtw_init_sema(&precvpriv->allrxreturnevt, 0);139140#endif141142res = rtw_hal_init_recv_priv(padapter);143144#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS145rtw_init_timer(&precvpriv->signal_stat_timer, padapter, rtw_signal_stat_timer_hdl, padapter);146147precvpriv->signal_stat_sampling_interval = 2000; /* ms */148/* precvpriv->signal_stat_converging_constant = 5000; */ /* ms */149150rtw_set_signal_stat_timer(precvpriv);151#endif /* CONFIG_NEW_SIGNAL_STAT_PROCESS */152153exit:154155156return res;157158}159160void rtw_mfree_recv_priv_lock(struct recv_priv *precvpriv);161void rtw_mfree_recv_priv_lock(struct recv_priv *precvpriv)162{163_rtw_spinlock_free(&precvpriv->lock);164#ifdef CONFIG_RECV_THREAD_MODE165_rtw_free_sema(&precvpriv->recv_sema);166#endif167168_rtw_spinlock_free(&precvpriv->free_recv_queue.lock);169_rtw_spinlock_free(&precvpriv->recv_pending_queue.lock);170171_rtw_spinlock_free(&precvpriv->free_recv_buf_queue.lock);172173#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX174_rtw_spinlock_free(&precvpriv->recv_buf_pending_queue.lock);175#endif /* CONFIG_USE_USB_BUFFER_ALLOC_RX */176}177178void _rtw_free_recv_priv(struct recv_priv *precvpriv)179{180_adapter *padapter = precvpriv->adapter;181182183rtw_free_uc_swdec_pending_queue(padapter);184185rtw_mfree_recv_priv_lock(precvpriv);186187rtw_os_recv_resource_free(precvpriv);188189if (precvpriv->pallocated_frame_buf)190rtw_vmfree(precvpriv->pallocated_frame_buf, NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);191192rtw_hal_free_recv_priv(padapter);193194195}196197bool rtw_rframe_del_wfd_ie(union recv_frame *rframe, u8 ies_offset)198{199#define DBG_RFRAME_DEL_WFD_IE 0200u8 *ies = rframe->u.hdr.rx_data + sizeof(struct rtw_ieee80211_hdr_3addr) + ies_offset;201uint ies_len_ori = rframe->u.hdr.len - (ies - rframe->u.hdr.rx_data);202uint ies_len;203204ies_len = rtw_del_wfd_ie(ies, ies_len_ori, DBG_RFRAME_DEL_WFD_IE ? __func__ : NULL);205rframe->u.hdr.len -= ies_len_ori - ies_len;206207return ies_len_ori != ies_len;208}209210union recv_frame *_rtw_alloc_recvframe(_queue *pfree_recv_queue)211{212213union recv_frame *precvframe;214_list *plist, *phead;215_adapter *padapter;216struct recv_priv *precvpriv;217218if (_rtw_queue_empty(pfree_recv_queue) == _TRUE)219precvframe = NULL;220else {221phead = get_list_head(pfree_recv_queue);222223plist = get_next(phead);224225precvframe = LIST_CONTAINOR(plist, union recv_frame, u);226227rtw_list_delete(&precvframe->u.hdr.list);228padapter = precvframe->u.hdr.adapter;229if (padapter != NULL) {230precvpriv = &padapter->recvpriv;231if (pfree_recv_queue == &precvpriv->free_recv_queue)232precvpriv->free_recvframe_cnt--;233}234}235236237return precvframe;238239}240241union recv_frame *rtw_alloc_recvframe(_queue *pfree_recv_queue)242{243_irqL irqL;244union recv_frame *precvframe;245246_enter_critical_bh(&pfree_recv_queue->lock, &irqL);247248precvframe = _rtw_alloc_recvframe(pfree_recv_queue);249250_exit_critical_bh(&pfree_recv_queue->lock, &irqL);251252return precvframe;253}254255void rtw_init_recvframe(union recv_frame *precvframe, struct recv_priv *precvpriv)256{257/* Perry: This can be removed */258_rtw_init_listhead(&precvframe->u.hdr.list);259260precvframe->u.hdr.len = 0;261}262263int rtw_free_recvframe(union recv_frame *precvframe, _queue *pfree_recv_queue)264{265_irqL irqL;266_adapter *padapter = precvframe->u.hdr.adapter;267struct recv_priv *precvpriv = &padapter->recvpriv;268269270#ifdef CONFIG_CONCURRENT_MODE271padapter = GET_PRIMARY_ADAPTER(padapter);272precvpriv = &padapter->recvpriv;273pfree_recv_queue = &precvpriv->free_recv_queue;274precvframe->u.hdr.adapter = padapter;275#endif276277278rtw_os_free_recvframe(precvframe);279280281_enter_critical_bh(&pfree_recv_queue->lock, &irqL);282283rtw_list_delete(&(precvframe->u.hdr.list));284285precvframe->u.hdr.len = 0;286287rtw_list_insert_tail(&(precvframe->u.hdr.list), get_list_head(pfree_recv_queue));288289if (padapter != NULL) {290if (pfree_recv_queue == &precvpriv->free_recv_queue)291precvpriv->free_recvframe_cnt++;292}293294_exit_critical_bh(&pfree_recv_queue->lock, &irqL);295296297return _SUCCESS;298299}300301302303304sint _rtw_enqueue_recvframe(union recv_frame *precvframe, _queue *queue)305{306307_adapter *padapter = precvframe->u.hdr.adapter;308struct recv_priv *precvpriv = &padapter->recvpriv;309310311/* _rtw_init_listhead(&(precvframe->u.hdr.list)); */312rtw_list_delete(&(precvframe->u.hdr.list));313314315rtw_list_insert_tail(&(precvframe->u.hdr.list), get_list_head(queue));316317if (padapter != NULL) {318if (queue == &precvpriv->free_recv_queue)319precvpriv->free_recvframe_cnt++;320}321322323return _SUCCESS;324}325326sint rtw_enqueue_recvframe(union recv_frame *precvframe, _queue *queue)327{328sint ret;329_irqL irqL;330331/* _spinlock(&pfree_recv_queue->lock); */332_enter_critical_bh(&queue->lock, &irqL);333ret = _rtw_enqueue_recvframe(precvframe, queue);334/* _rtw_spinunlock(&pfree_recv_queue->lock); */335_exit_critical_bh(&queue->lock, &irqL);336337return ret;338}339340/*341sint rtw_enqueue_recvframe(union recv_frame *precvframe, _queue *queue)342{343return rtw_free_recvframe(precvframe, queue);344}345*/346347348349350/*351caller : defrag ; recvframe_chk_defrag in recv_thread (passive)352pframequeue: defrag_queue : will be accessed in recv_thread (passive)353354using spinlock to protect355356*/357358void rtw_free_recvframe_queue(_queue *pframequeue, _queue *pfree_recv_queue)359{360union recv_frame *precvframe;361_list *plist, *phead;362363_rtw_spinlock(&pframequeue->lock);364365phead = get_list_head(pframequeue);366plist = get_next(phead);367368while (rtw_end_of_queue_search(phead, plist) == _FALSE) {369precvframe = LIST_CONTAINOR(plist, union recv_frame, u);370371plist = get_next(plist);372373/* rtw_list_delete(&precvframe->u.hdr.list); */ /* will do this in rtw_free_recvframe() */374375rtw_free_recvframe(precvframe, pfree_recv_queue);376}377378_rtw_spinunlock(&pframequeue->lock);379380381}382383u32 rtw_free_uc_swdec_pending_queue(_adapter *adapter)384{385u32 cnt = 0;386union recv_frame *pending_frame;387while ((pending_frame = rtw_alloc_recvframe(&adapter->recvpriv.uc_swdec_pending_queue))) {388rtw_free_recvframe(pending_frame, &adapter->recvpriv.free_recv_queue);389cnt++;390}391392if (cnt)393RTW_INFO(FUNC_ADPT_FMT" dequeue %d\n", FUNC_ADPT_ARG(adapter), cnt);394395return cnt;396}397398399sint rtw_enqueue_recvbuf_to_head(struct recv_buf *precvbuf, _queue *queue)400{401_irqL irqL;402403_enter_critical_bh(&queue->lock, &irqL);404405rtw_list_delete(&precvbuf->list);406rtw_list_insert_head(&precvbuf->list, get_list_head(queue));407408_exit_critical_bh(&queue->lock, &irqL);409410return _SUCCESS;411}412413sint rtw_enqueue_recvbuf(struct recv_buf *precvbuf, _queue *queue)414{415_irqL irqL;416#ifdef CONFIG_SDIO_HCI417_enter_critical_bh(&queue->lock, &irqL);418#else419_enter_critical_ex(&queue->lock, &irqL);420#endif/*#ifdef CONFIG_SDIO_HCI*/421422rtw_list_delete(&precvbuf->list);423424rtw_list_insert_tail(&precvbuf->list, get_list_head(queue));425#ifdef CONFIG_SDIO_HCI426_exit_critical_bh(&queue->lock, &irqL);427#else428_exit_critical_ex(&queue->lock, &irqL);429#endif/*#ifdef CONFIG_SDIO_HCI*/430return _SUCCESS;431432}433434struct recv_buf *rtw_dequeue_recvbuf(_queue *queue)435{436_irqL irqL;437struct recv_buf *precvbuf;438_list *plist, *phead;439440#ifdef CONFIG_SDIO_HCI441_enter_critical_bh(&queue->lock, &irqL);442#else443_enter_critical_ex(&queue->lock, &irqL);444#endif/*#ifdef CONFIG_SDIO_HCI*/445446if (_rtw_queue_empty(queue) == _TRUE)447precvbuf = NULL;448else {449phead = get_list_head(queue);450451plist = get_next(phead);452453precvbuf = LIST_CONTAINOR(plist, struct recv_buf, list);454455rtw_list_delete(&precvbuf->list);456457}458459#ifdef CONFIG_SDIO_HCI460_exit_critical_bh(&queue->lock, &irqL);461#else462_exit_critical_ex(&queue->lock, &irqL);463#endif/*#ifdef CONFIG_SDIO_HCI*/464465return precvbuf;466467}468469sint recvframe_chkmic(_adapter *adapter, union recv_frame *precvframe);470sint recvframe_chkmic(_adapter *adapter, union recv_frame *precvframe)471{472473sint i, res = _SUCCESS;474u32 datalen;475u8 miccode[8];476u8 bmic_err = _FALSE, brpt_micerror = _TRUE;477u8 *pframe, *payload, *pframemic;478u8 *mickey;479/* u8 *iv,rxdata_key_idx=0; */480struct sta_info *stainfo;481struct rx_pkt_attrib *prxattrib = &precvframe->u.hdr.attrib;482struct security_priv *psecuritypriv = &adapter->securitypriv;483484struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;485struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);486487stainfo = rtw_get_stainfo(&adapter->stapriv , &prxattrib->ta[0]);488489if (prxattrib->encrypt == _TKIP_) {490491/* calculate mic code */492if (stainfo != NULL) {493if (IS_MCAST(prxattrib->ra)) {494/* mickey=&psecuritypriv->dot118021XGrprxmickey.skey[0]; */495/* iv = precvframe->u.hdr.rx_data+prxattrib->hdrlen; */496/* rxdata_key_idx =( ((iv[3])>>6)&0x3) ; */497mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0];498499/* RTW_INFO("\n recvframe_chkmic: bcmc key psecuritypriv->dot118021XGrpKeyid(%d),pmlmeinfo->key_index(%d) ,recv key_id(%d)\n", */500/* psecuritypriv->dot118021XGrpKeyid,pmlmeinfo->key_index,rxdata_key_idx); */501502if (psecuritypriv->binstallGrpkey == _FALSE) {503res = _FAIL;504RTW_INFO("\n recvframe_chkmic:didn't install group key!!!!!!!!!!\n");505goto exit;506}507} else {508mickey = &stainfo->dot11tkiprxmickey.skey[0];509}510511datalen = precvframe->u.hdr.len - prxattrib->hdrlen - prxattrib->iv_len - prxattrib->icv_len - 8; /* icv_len included the mic code */512pframe = precvframe->u.hdr.rx_data;513payload = pframe + prxattrib->hdrlen + prxattrib->iv_len;514515516/* rtw_seccalctkipmic(&stainfo->dot11tkiprxmickey.skey[0],pframe,payload, datalen ,&miccode[0],(unsigned char)prxattrib->priority); */ /* care the length of the data */517518rtw_seccalctkipmic(mickey, pframe, payload, datalen , &miccode[0], (unsigned char)prxattrib->priority); /* care the length of the data */519520pframemic = payload + datalen;521522bmic_err = _FALSE;523524for (i = 0; i < 8; i++) {525if (miccode[i] != *(pframemic + i)) {526bmic_err = _TRUE;527}528}529530531if (bmic_err == _TRUE) {532533534535/* double check key_index for some timing issue , */536/* cannot compare with psecuritypriv->dot118021XGrpKeyid also cause timing issue */537if ((IS_MCAST(prxattrib->ra) == _TRUE) && (prxattrib->key_index != pmlmeinfo->key_index))538brpt_micerror = _FALSE;539540if ((prxattrib->bdecrypted == _TRUE) && (brpt_micerror == _TRUE)) {541rtw_handle_tkip_mic_err(adapter, stainfo, (u8)IS_MCAST(prxattrib->ra));542RTW_INFO(" mic error :prxattrib->bdecrypted=%d\n", prxattrib->bdecrypted);543} else {544RTW_INFO(" mic error :prxattrib->bdecrypted=%d\n", prxattrib->bdecrypted);545}546547res = _FAIL;548549} else {550/* mic checked ok */551if ((psecuritypriv->bcheck_grpkey == _FALSE) && (IS_MCAST(prxattrib->ra) == _TRUE)) {552psecuritypriv->bcheck_grpkey = _TRUE;553}554}555556}557558recvframe_pull_tail(precvframe, 8);559560}561562exit:563564565return res;566567}568569/*#define DBG_RX_SW_DECRYPTOR*/570571/* decrypt and set the ivlen,icvlen of the recv_frame */572union recv_frame *decryptor(_adapter *padapter, union recv_frame *precv_frame);573union recv_frame *decryptor(_adapter *padapter, union recv_frame *precv_frame)574{575576struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib;577struct security_priv *psecuritypriv = &padapter->securitypriv;578union recv_frame *return_packet = precv_frame;579u32 res = _SUCCESS;580581582DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt);583584585if (prxattrib->encrypt > 0) {586u8 *iv = precv_frame->u.hdr.rx_data + prxattrib->hdrlen;587prxattrib->key_index = (((iv[3]) >> 6) & 0x3) ;588589if (prxattrib->key_index > WEP_KEYS) {590RTW_INFO("prxattrib->key_index(%d) > WEP_KEYS\n", prxattrib->key_index);591592switch (prxattrib->encrypt) {593case _WEP40_:594case _WEP104_:595prxattrib->key_index = psecuritypriv->dot11PrivacyKeyIndex;596break;597case _TKIP_:598case _AES_:599default:600prxattrib->key_index = psecuritypriv->dot118021XGrpKeyid;601break;602}603}604}605606if (prxattrib->encrypt && !prxattrib->bdecrypted) {607if (GetFrameType(get_recvframe_data(precv_frame)) == WIFI_DATA608#ifdef CONFIG_CONCURRENT_MODE609&& !IS_MCAST(prxattrib->ra) /* bc/mc packets may use sw decryption for concurrent mode */610#endif611)612psecuritypriv->hw_decrypted = _FALSE;613614#ifdef DBG_RX_SW_DECRYPTOR615RTW_INFO(ADPT_FMT" - sec_type:%s DO SW decryption\n",616ADPT_ARG(padapter), security_type_str(prxattrib->encrypt));617#endif618619#ifdef DBG_RX_DECRYPTOR620RTW_INFO("[%s] %d:prxstat->bdecrypted:%d, prxattrib->encrypt:%d, Setting psecuritypriv->hw_decrypted = %d\n",621__FUNCTION__,622__LINE__,623prxattrib->bdecrypted,624prxattrib->encrypt,625psecuritypriv->hw_decrypted);626#endif627628switch (prxattrib->encrypt) {629case _WEP40_:630case _WEP104_:631DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_wep);632rtw_wep_decrypt(padapter, (u8 *)precv_frame);633break;634case _TKIP_:635DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_tkip);636res = rtw_tkip_decrypt(padapter, (u8 *)precv_frame);637break;638case _AES_:639DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_aes);640res = rtw_aes_decrypt(padapter, (u8 *)precv_frame);641break;642#ifdef CONFIG_WAPI_SUPPORT643case _SMS4_:644DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_wapi);645rtw_sms4_decrypt(padapter, (u8 *)precv_frame);646break;647#endif648default:649break;650}651} else if (prxattrib->bdecrypted == 1652&& prxattrib->encrypt > 0653&& (psecuritypriv->busetkipkey == 1 || prxattrib->encrypt != _TKIP_)654) {655#if 0656if ((prxstat->icv == 1) && (prxattrib->encrypt != _AES_)) {657psecuritypriv->hw_decrypted = _FALSE;658659660rtw_free_recvframe(precv_frame, &padapter->recvpriv.free_recv_queue);661662return_packet = NULL;663664} else665#endif666{667DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_hw);668669psecuritypriv->hw_decrypted = _TRUE;670#ifdef DBG_RX_DECRYPTOR671RTW_INFO("[%s] %d:prxstat->bdecrypted:%d, prxattrib->encrypt:%d, Setting psecuritypriv->hw_decrypted = %d\n",672__FUNCTION__,673__LINE__,674prxattrib->bdecrypted,675prxattrib->encrypt,676psecuritypriv->hw_decrypted);677678#endif679}680} else {681DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_unknown);682#ifdef DBG_RX_DECRYPTOR683RTW_INFO("[%s] %d:prxstat->bdecrypted:%d, prxattrib->encrypt:%d, Setting psecuritypriv->hw_decrypted = %d\n",684__FUNCTION__,685__LINE__,686prxattrib->bdecrypted,687prxattrib->encrypt,688psecuritypriv->hw_decrypted);689#endif690}691692#ifdef CONFIG_RTW_MESH693if (res != _FAIL694&& !prxattrib->amsdu695&& prxattrib->mesh_ctrl_present)696res = rtw_mesh_rx_validate_mctrl_non_amsdu(padapter, precv_frame);697#endif698699if (res == _FAIL) {700rtw_free_recvframe(return_packet, &padapter->recvpriv.free_recv_queue);701return_packet = NULL;702} else703prxattrib->bdecrypted = _TRUE;704/* recvframe_chkmic(adapter, precv_frame); */ /* move to recvframme_defrag function */705706707return return_packet;708709}710/* ###set the security information in the recv_frame */711union recv_frame *portctrl(_adapter *adapter, union recv_frame *precv_frame);712union recv_frame *portctrl(_adapter *adapter, union recv_frame *precv_frame)713{714u8 *psta_addr = NULL;715u8 *ptr;716uint auth_alg;717struct recv_frame_hdr *pfhdr;718struct sta_info *psta;719struct sta_priv *pstapriv ;720union recv_frame *prtnframe;721u16 ether_type = 0;722u16 eapol_type = 0x888e;/* for Funia BD's WPA issue */723struct rx_pkt_attrib *pattrib;724725726pstapriv = &adapter->stapriv;727728auth_alg = adapter->securitypriv.dot11AuthAlgrthm;729730ptr = get_recvframe_data(precv_frame);731pfhdr = &precv_frame->u.hdr;732pattrib = &pfhdr->attrib;733psta_addr = pattrib->ta;734735prtnframe = NULL;736737psta = rtw_get_stainfo(pstapriv, psta_addr);738739740if (auth_alg == dot11AuthAlgrthm_8021X) {741if ((psta != NULL) && (psta->ieee8021x_blocked)) {742/* blocked */743/* only accept EAPOL frame */744745prtnframe = precv_frame;746747/* get ether_type */748ptr = ptr + pfhdr->attrib.hdrlen + pfhdr->attrib.iv_len + LLC_HEADER_SIZE;749_rtw_memcpy(ðer_type, ptr, 2);750ether_type = ntohs((unsigned short)ether_type);751752if (ether_type == eapol_type)753prtnframe = precv_frame;754else {755/* free this frame */756rtw_free_recvframe(precv_frame, &adapter->recvpriv.free_recv_queue);757prtnframe = NULL;758}759} else {760/* allowed */761/* check decryption status, and decrypt the frame if needed */762763764prtnframe = precv_frame;765/* check is the EAPOL frame or not (Rekey) */766/* if(ether_type == eapol_type){ */767/* check Rekey */768769/* prtnframe=precv_frame; */770/* } */771}772} else773prtnframe = precv_frame;774775776return prtnframe;777778}779780/* VALID_PN_CHK781* Return true when PN is legal, otherwise false.782* Legal PN:783* 1. If old PN is 0, any PN is legal784* 2. PN > old PN785*/786#define PN_LESS_CHK(a, b) (((a-b) & 0x800000000000) != 0)787#define VALID_PN_CHK(new, old) (((old) == 0) || PN_LESS_CHK(old, new))788#define CCMPH_2_KEYID(ch) (((ch) & 0x00000000c0000000) >> 30)789sint recv_ucast_pn_decache(union recv_frame *precv_frame);790sint recv_ucast_pn_decache(union recv_frame *precv_frame)791{792struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;793struct sta_info *sta = precv_frame->u.hdr.psta;794struct stainfo_rxcache *prxcache = &sta->sta_recvpriv.rxcache;795u8 *pdata = precv_frame->u.hdr.rx_data;796sint tid = precv_frame->u.hdr.attrib.priority;797u64 tmp_iv_hdr = 0;798u64 curr_pn = 0, pkt_pn = 0;799800if (tid > 15)801return _FAIL;802803if (pattrib->encrypt == _AES_) {804tmp_iv_hdr = le64_to_cpu(*(u64*)(pdata + pattrib->hdrlen));805pkt_pn = CCMPH_2_PN(tmp_iv_hdr);806tmp_iv_hdr = le64_to_cpu(*(u64*)prxcache->iv[tid]);807curr_pn = CCMPH_2_PN(tmp_iv_hdr);808809if (!VALID_PN_CHK(pkt_pn, curr_pn)) {810/* return _FAIL; */811} else {812prxcache->last_tid = tid;813_rtw_memcpy(prxcache->iv[tid],814(pdata + pattrib->hdrlen),815sizeof(prxcache->iv[tid]));816}817}818819return _SUCCESS;820}821822sint recv_bcast_pn_decache(union recv_frame *precv_frame);823sint recv_bcast_pn_decache(union recv_frame *precv_frame)824{825_adapter *padapter = precv_frame->u.hdr.adapter;826struct mlme_priv *pmlmepriv = &padapter->mlmepriv;827struct security_priv *psecuritypriv = &padapter->securitypriv;828struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;829u8 *pdata = precv_frame->u.hdr.rx_data;830u64 tmp_iv_hdr = 0;831u64 curr_pn = 0, pkt_pn = 0;832u8 key_id;833834if ((pattrib->encrypt == _AES_) &&835(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)) {836837tmp_iv_hdr = le64_to_cpu(*(u64*)(pdata + pattrib->hdrlen));838key_id = CCMPH_2_KEYID(tmp_iv_hdr);839pkt_pn = CCMPH_2_PN(tmp_iv_hdr);840841curr_pn = le64_to_cpu(*(u64*)psecuritypriv->iv_seq[key_id]);842curr_pn &= 0x0000ffffffffffff;843844if (!VALID_PN_CHK(pkt_pn, curr_pn))845return _FAIL;846847*(u64*)psecuritypriv->iv_seq[key_id] = cpu_to_le64(pkt_pn);848}849850return _SUCCESS;851}852853sint recv_decache(union recv_frame *precv_frame)854{855struct sta_info *psta = precv_frame->u.hdr.psta;856struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;857_adapter *adapter = psta->padapter;858sint tid = pattrib->priority;859u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num & 0xffff) << 4) |860(precv_frame->u.hdr.attrib.frag_num & 0xf);861u16 *prxseq;862863if (tid > 15)864return _FAIL;865866if (pattrib->qos) {867if (IS_MCAST(pattrib->ra))868prxseq = &psta->sta_recvpriv.bmc_tid_rxseq[tid];869else870prxseq = &psta->sta_recvpriv.rxcache.tid_rxseq[tid];871} else {872if (IS_MCAST(pattrib->ra)) {873prxseq = &psta->sta_recvpriv.nonqos_bmc_rxseq;874#ifdef DBG_RX_SEQ875RTW_INFO("DBG_RX_SEQ "FUNC_ADPT_FMT" nonqos bmc seq_num:%d\n"876, FUNC_ADPT_ARG(adapter), pattrib->seq_num);877#endif878879} else {880prxseq = &psta->sta_recvpriv.nonqos_rxseq;881#ifdef DBG_RX_SEQ882RTW_INFO("DBG_RX_SEQ "FUNC_ADPT_FMT" nonqos seq_num:%d\n"883, FUNC_ADPT_ARG(adapter), pattrib->seq_num);884#endif885}886}887888if (seq_ctrl == *prxseq) {889/* for non-AMPDU case */890psta->sta_stats.duplicate_cnt++;891892if (psta->sta_stats.duplicate_cnt % 100 == 0)893RTW_INFO("%s: tid=%u seq=%d frag=%d\n", __func__894, tid, precv_frame->u.hdr.attrib.seq_num895, precv_frame->u.hdr.attrib.frag_num);896897#ifdef DBG_RX_DROP_FRAME898RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" recv_decache _FAIL for sta="MAC_FMT"\n"899, FUNC_ADPT_ARG(adapter), MAC_ARG(psta->cmn.mac_addr));900#endif901return _FAIL;902}903*prxseq = seq_ctrl;904905return _SUCCESS;906}907908void process_pwrbit_data(_adapter *padapter, union recv_frame *precv_frame, struct sta_info *psta)909{910#ifdef CONFIG_AP_MODE911unsigned char pwrbit;912u8 *ptr = precv_frame->u.hdr.rx_data;913914pwrbit = GetPwrMgt(ptr);915916if (pwrbit) {917if (!(psta->state & WIFI_SLEEP_STATE)) {918/* psta->state |= WIFI_SLEEP_STATE; */919/* rtw_tim_map_set(padapter, pstapriv->sta_dz_bitmap, BIT(psta->cmn.aid)); */920921stop_sta_xmit(padapter, psta);922/* RTW_INFO_DUMP("to sleep, sta_dz_bitmap=", pstapriv->sta_dz_bitmap, pstapriv->aid_bmp_len); */923}924} else {925if (psta->state & WIFI_SLEEP_STATE) {926/* psta->state ^= WIFI_SLEEP_STATE; */927/* rtw_tim_map_clear(padapter, pstapriv->sta_dz_bitmap, BIT(psta->cmn.aid)); */928929wakeup_sta_to_xmit(padapter, psta);930/* RTW_INFO_DUMP("to wakeup, sta_dz_bitmap=", pstapriv->sta_dz_bitmap, pstapriv->aid_bmp_len); */931}932}933#endif934}935936void process_wmmps_data(_adapter *padapter, union recv_frame *precv_frame, struct sta_info *psta)937{938#ifdef CONFIG_AP_MODE939struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;940941#ifdef CONFIG_TDLS942if (!(psta->tdls_sta_state & TDLS_LINKED_STATE)) {943#endif /* CONFIG_TDLS */944945if (!psta->qos_option)946return;947948if (!(psta->qos_info & 0xf))949return;950951#ifdef CONFIG_TDLS952}953#endif /* CONFIG_TDLS */954955if (psta->state & WIFI_SLEEP_STATE) {956u8 wmmps_ac = 0;957958switch (pattrib->priority) {959case 1:960case 2:961wmmps_ac = psta->uapsd_bk & BIT(1);962break;963case 4:964case 5:965wmmps_ac = psta->uapsd_vi & BIT(1);966break;967case 6:968case 7:969wmmps_ac = psta->uapsd_vo & BIT(1);970break;971case 0:972case 3:973default:974wmmps_ac = psta->uapsd_be & BIT(1);975break;976}977978if (wmmps_ac) {979if (psta->sleepq_ac_len > 0) {980/* process received triggered frame */981xmit_delivery_enabled_frames(padapter, psta);982} else {983/* issue one qos null frame with More data bit = 0 and the EOSP bit set (=1) */984issue_qos_nulldata(padapter, psta->cmn.mac_addr, (u16)pattrib->priority, 0, 0, 0);985}986}987988}989990991#endif992993}994995#ifdef CONFIG_TDLS996sint OnTDLS(_adapter *adapter, union recv_frame *precv_frame)997{998struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;999sint ret = _SUCCESS;1000u8 *paction = get_recvframe_data(precv_frame);1001u8 category_field = 1;1002#ifdef CONFIG_WFD1003u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a };1004#endif /* CONFIG_WFD */1005struct tdls_info *ptdlsinfo = &(adapter->tdlsinfo);1006u8 *ptr = precv_frame->u.hdr.rx_data;1007struct sta_priv *pstapriv = &(adapter->stapriv);1008struct sta_info *ptdls_sta = NULL;10091010/* point to action field */1011paction += pattrib->hdrlen1012+ pattrib->iv_len1013+ SNAP_SIZE1014+ ETH_TYPE_LEN1015+ PAYLOAD_TYPE_LEN1016+ category_field;10171018RTW_INFO("[TDLS] Recv %s from "MAC_FMT" with SeqNum = %d\n", rtw_tdls_action_txt(*paction), MAC_ARG(pattrib->src), GetSequence(get_recvframe_data(precv_frame)));10191020if (hal_chk_wl_func(adapter, WL_FUNC_TDLS) == _FALSE) {1021RTW_INFO("Ignore tdls frame since hal doesn't support tdls\n");1022ret = _FAIL;1023return ret;1024}10251026if (rtw_is_tdls_enabled(adapter) == _FALSE) {1027RTW_INFO("recv tdls frame, "1028"but tdls haven't enabled\n");1029ret = _FAIL;1030return ret;1031}10321033ptdls_sta = rtw_get_stainfo(pstapriv, get_sa(ptr));1034if (ptdls_sta == NULL) {1035switch (*paction) {1036case TDLS_SETUP_REQUEST:1037case TDLS_DISCOVERY_REQUEST:1038break;1039default:1040RTW_INFO("[TDLS] %s - Direct Link Peer = "MAC_FMT" not found for action = %d\n", __func__, MAC_ARG(get_sa(ptr)), *paction);1041ret = _FAIL;1042goto exit;1043}1044}10451046switch (*paction) {1047case TDLS_SETUP_REQUEST:1048ret = On_TDLS_Setup_Req(adapter, precv_frame, ptdls_sta);1049break;1050case TDLS_SETUP_RESPONSE:1051ret = On_TDLS_Setup_Rsp(adapter, precv_frame, ptdls_sta);1052break;1053case TDLS_SETUP_CONFIRM:1054ret = On_TDLS_Setup_Cfm(adapter, precv_frame, ptdls_sta);1055break;1056case TDLS_TEARDOWN:1057ret = On_TDLS_Teardown(adapter, precv_frame, ptdls_sta);1058break;1059case TDLS_DISCOVERY_REQUEST:1060ret = On_TDLS_Dis_Req(adapter, precv_frame);1061break;1062case TDLS_PEER_TRAFFIC_INDICATION:1063ret = On_TDLS_Peer_Traffic_Indication(adapter, precv_frame, ptdls_sta);1064break;1065case TDLS_PEER_TRAFFIC_RESPONSE:1066ret = On_TDLS_Peer_Traffic_Rsp(adapter, precv_frame, ptdls_sta);1067break;1068#ifdef CONFIG_TDLS_CH_SW1069case TDLS_CHANNEL_SWITCH_REQUEST:1070ret = On_TDLS_Ch_Switch_Req(adapter, precv_frame, ptdls_sta);1071break;1072case TDLS_CHANNEL_SWITCH_RESPONSE:1073ret = On_TDLS_Ch_Switch_Rsp(adapter, precv_frame, ptdls_sta);1074break;1075#endif1076#ifdef CONFIG_WFD1077/* First byte of WFA OUI */1078case 0x50:1079if (_rtw_memcmp(WFA_OUI, paction, 3)) {1080/* Probe request frame */1081if (*(paction + 3) == 0x04) {1082/* WFDTDLS: for sigma test, do not setup direct link automatically */1083ptdlsinfo->dev_discovered = _TRUE;1084RTW_INFO("recv tunneled probe request frame\n");1085issue_tunneled_probe_rsp(adapter, precv_frame);1086}1087/* Probe response frame */1088if (*(paction + 3) == 0x05) {1089/* WFDTDLS: for sigma test, do not setup direct link automatically */1090ptdlsinfo->dev_discovered = _TRUE;1091RTW_INFO("recv tunneled probe response frame\n");1092}1093}1094break;1095#endif /* CONFIG_WFD */1096default:1097RTW_INFO("receive TDLS frame %d but not support\n", *paction);1098ret = _FAIL;1099break;1100}11011102exit:1103return ret;11041105}1106#endif /* CONFIG_TDLS */11071108void count_rx_stats(_adapter *padapter, union recv_frame *prframe, struct sta_info *sta)1109{1110int sz;1111struct sta_info *psta = NULL;1112struct stainfo_stats *pstats = NULL;1113struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;1114struct recv_priv *precvpriv = &padapter->recvpriv;11151116sz = get_recvframe_len(prframe);1117precvpriv->rx_bytes += sz;11181119padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++;11201121if ((!MacAddr_isBcst(pattrib->dst)) && (!IS_MCAST(pattrib->dst)))1122padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++;11231124if (sta)1125psta = sta;1126else1127psta = prframe->u.hdr.psta;11281129if (psta) {1130u8 is_ra_bmc = IS_MCAST(pattrib->ra);11311132pstats = &psta->sta_stats;11331134pstats->last_rx_time = rtw_get_current_time();1135pstats->rx_data_pkts++;1136pstats->rx_bytes += sz;1137if (is_broadcast_mac_addr(pattrib->ra)) {1138pstats->rx_data_bc_pkts++;1139pstats->rx_bc_bytes += sz;1140} else if (is_ra_bmc) {1141pstats->rx_data_mc_pkts++;1142pstats->rx_mc_bytes += sz;1143}11441145if (!is_ra_bmc) {1146pstats->rxratecnt[pattrib->data_rate]++;1147/*record rx packets for every tid*/1148pstats->rx_data_qos_pkts[pattrib->priority]++;1149}1150#ifdef CONFIG_DYNAMIC_SOML1151rtw_dyn_soml_byte_update(padapter, pattrib->data_rate, sz);1152#endif1153#if defined(CONFIG_CHECK_LEAVE_LPS) && defined(CONFIG_LPS_CHK_BY_TP)1154if (adapter_to_pwrctl(padapter)->lps_chk_by_tp)1155traffic_check_for_leave_lps_by_tp(padapter, _FALSE, psta);1156#endif /* CONFIG_LPS */11571158}11591160#ifdef CONFIG_CHECK_LEAVE_LPS1161#ifdef CONFIG_LPS_CHK_BY_TP1162if (!adapter_to_pwrctl(padapter)->lps_chk_by_tp)1163#endif1164traffic_check_for_leave_lps(padapter, _FALSE, 0);1165#endif /* CONFIG_CHECK_LEAVE_LPS */11661167}11681169sint sta2sta_data_frame(1170_adapter *adapter,1171union recv_frame *precv_frame,1172struct sta_info **psta1173)1174{1175u8 *ptr = precv_frame->u.hdr.rx_data;1176sint ret = _SUCCESS;1177struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;1178struct sta_priv *pstapriv = &adapter->stapriv;1179struct mlme_priv *pmlmepriv = &adapter->mlmepriv;1180u8 *mybssid = get_bssid(pmlmepriv);1181u8 *myhwaddr = adapter_mac_addr(adapter);1182u8 *sta_addr = pattrib->ta;1183sint bmcast = IS_MCAST(pattrib->dst);11841185#ifdef CONFIG_TDLS1186struct tdls_info *ptdlsinfo = &adapter->tdlsinfo;1187#ifdef CONFIG_TDLS_CH_SW1188struct tdls_ch_switch *pchsw_info = &ptdlsinfo->chsw_info;1189#endif1190struct sta_info *ptdls_sta = NULL;1191u8 *psnap_type = ptr + pattrib->hdrlen + pattrib->iv_len + SNAP_SIZE;1192/* frame body located after [+2]: ether-type, [+1]: payload type */1193u8 *pframe_body = psnap_type + 2 + 1;1194#endif119511961197/* RTW_INFO("[%s] %d, seqnum:%d\n", __FUNCTION__, __LINE__, pattrib->seq_num); */11981199if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) ||1200(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)) {12011202/* filter packets that SA is myself or multicast or broadcast */1203if (_rtw_memcmp(myhwaddr, pattrib->src, ETH_ALEN)) {1204ret = _FAIL;1205goto exit;1206}12071208if ((!_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) {1209ret = _FAIL;1210goto exit;1211}12121213if (_rtw_memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||1214_rtw_memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||1215(!_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN))) {1216ret = _FAIL;1217goto exit;1218}12191220} else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE) {1221#ifdef CONFIG_TDLS12221223/* direct link data transfer */1224if (ptdlsinfo->link_established == _TRUE) {1225*psta = ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->ta);1226if (ptdls_sta == NULL) {1227ret = _FAIL;1228goto exit;1229} else if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) {1230/* filter packets that SA is myself or multicast or broadcast */1231if (_rtw_memcmp(myhwaddr, pattrib->src, ETH_ALEN)) {1232ret = _FAIL;1233goto exit;1234}1235/* da should be for me */1236if ((!_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) {1237ret = _FAIL;1238goto exit;1239}1240/* check BSSID */1241if (_rtw_memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||1242_rtw_memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||1243(!_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN))) {1244ret = _FAIL;1245goto exit;1246}12471248#ifdef CONFIG_TDLS_CH_SW1249if (ATOMIC_READ(&pchsw_info->chsw_on) == _TRUE) {1250if (adapter->mlmeextpriv.cur_channel != rtw_get_oper_ch(adapter)) {1251pchsw_info->ch_sw_state |= TDLS_PEER_AT_OFF_STATE;1252if (!(pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE))1253_cancel_timer_ex(&ptdls_sta->ch_sw_timer);1254/* On_TDLS_Peer_Traffic_Rsp(adapter, precv_frame); */1255}1256}1257#endif12581259/* process UAPSD tdls sta */1260process_pwrbit_data(adapter, precv_frame, ptdls_sta);12611262/* if NULL-frame, check pwrbit */1263if ((get_frame_sub_type(ptr) & WIFI_DATA_NULL) == WIFI_DATA_NULL) {1264/* NULL-frame with pwrbit=1, buffer_STA should buffer frames for sleep_STA */1265if (GetPwrMgt(ptr)) {1266/* it would be triggered when we are off channel and receiving NULL DATA */1267/* we can confirm that peer STA is at off channel */1268RTW_INFO("TDLS: recv peer null frame with pwr bit 1\n");1269/* ptdls_sta->tdls_sta_state|=TDLS_PEER_SLEEP_STATE; */1270}12711272/* TODO: Updated BSSID's seq. */1273/* RTW_INFO("drop Null Data\n"); */1274ptdls_sta->tdls_sta_state &= ~(TDLS_WAIT_PTR_STATE);1275ret = _FAIL;1276goto exit;1277}12781279/* receive some of all TDLS management frames, process it at ON_TDLS */1280if (_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_TDLS, 2)) {1281ret = OnTDLS(adapter, precv_frame);1282goto exit;1283}12841285if ((get_frame_sub_type(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE)1286process_wmmps_data(adapter, precv_frame, ptdls_sta);12871288ptdls_sta->tdls_sta_state &= ~(TDLS_WAIT_PTR_STATE);12891290}1291} else1292#endif /* CONFIG_TDLS */1293{1294/* For Station mode, sa and bssid should always be BSSID, and DA is my mac-address */1295if (!_rtw_memcmp(pattrib->bssid, pattrib->src, ETH_ALEN)) {1296ret = _FAIL;1297goto exit;1298}1299}13001301} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) {1302if (bmcast) {1303/* For AP mode, if DA == MCAST, then BSSID should be also MCAST */1304if (!IS_MCAST(pattrib->bssid)) {1305ret = _FAIL;1306goto exit;1307}1308} else { /* not mc-frame */1309/* For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID */1310if (!_rtw_memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN)) {1311ret = _FAIL;1312goto exit;1313}1314}13151316} else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE) {1317_rtw_memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);1318_rtw_memcpy(pattrib->src, get_addr2_ptr(ptr), ETH_ALEN);1319_rtw_memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);1320_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);1321_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);13221323sta_addr = mybssid;1324} else1325ret = _FAIL;13261327#ifdef CONFIG_TDLS1328if (ptdls_sta == NULL)1329#endif1330*psta = rtw_get_stainfo(pstapriv, sta_addr);13311332if (*psta == NULL) {1333#ifdef CONFIG_MP_INCLUDED1334if (adapter->registrypriv.mp_mode == 1) {1335if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE)1336adapter->mppriv.rx_pktloss++;1337}1338#endif1339ret = _FAIL;1340goto exit;1341}13421343exit:1344return ret;13451346}13471348sint ap2sta_data_frame(1349_adapter *adapter,1350union recv_frame *precv_frame,1351struct sta_info **psta)1352{1353u8 *ptr = precv_frame->u.hdr.rx_data;1354struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;1355sint ret = _SUCCESS;1356struct sta_priv *pstapriv = &adapter->stapriv;1357struct mlme_priv *pmlmepriv = &adapter->mlmepriv;1358u8 *mybssid = get_bssid(pmlmepriv);1359u8 *myhwaddr = adapter_mac_addr(adapter);1360sint bmcast = IS_MCAST(pattrib->dst);136113621363if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)1364&& (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE1365|| check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE)1366) {13671368/* filter packets that SA is myself or multicast or broadcast */1369if (_rtw_memcmp(myhwaddr, pattrib->src, ETH_ALEN)) {1370#ifdef DBG_RX_DROP_FRAME1371RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" SA="MAC_FMT", myhwaddr="MAC_FMT"\n"1372, FUNC_ADPT_ARG(adapter), MAC_ARG(pattrib->src), MAC_ARG(myhwaddr));1373#endif1374ret = _FAIL;1375goto exit;1376}13771378/* da should be for me */1379if ((!_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) {1380#ifdef DBG_RX_DROP_FRAME1381RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA="MAC_FMT"\n"1382, FUNC_ADPT_ARG(adapter), MAC_ARG(pattrib->dst));1383#endif1384ret = _FAIL;1385goto exit;1386}138713881389/* check BSSID */1390if (_rtw_memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||1391_rtw_memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||1392(!_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN))) {1393#ifdef DBG_RX_DROP_FRAME1394RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" BSSID="MAC_FMT", mybssid="MAC_FMT"\n"1395, FUNC_ADPT_ARG(adapter), MAC_ARG(pattrib->bssid), MAC_ARG(mybssid));1396#endif1397#ifndef CONFIG_CUSTOMER_ALIBABA_GENERAL1398if (!bmcast1399&& !IS_RADAR_DETECTED(adapter_to_rfctl(adapter))1400) {1401RTW_INFO(ADPT_FMT" -issue_deauth to the nonassociated ap=" MAC_FMT " for the reason(7)\n", ADPT_ARG(adapter), MAC_ARG(pattrib->bssid));1402issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);1403}1404#endif1405ret = _FAIL;1406goto exit;1407}14081409*psta = rtw_get_stainfo(pstapriv, pattrib->ta);1410if (*psta == NULL) {1411#ifdef DBG_RX_DROP_FRAME1412RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" can't get psta under STATION_MODE ; drop pkt\n"1413, FUNC_ADPT_ARG(adapter));1414#endif1415ret = _FAIL;1416goto exit;1417}14181419/*if ((get_frame_sub_type(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) {1420}1421*/14221423if (get_frame_sub_type(ptr) & BIT(6)) {1424/* No data, will not indicate to upper layer, temporily count it here */1425count_rx_stats(adapter, precv_frame, *psta);1426ret = RTW_RX_HANDLED;1427goto exit;1428}14291430} else if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE) &&1431(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)) {1432_rtw_memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);1433_rtw_memcpy(pattrib->src, get_addr2_ptr(ptr), ETH_ALEN);1434_rtw_memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);1435_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);1436_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);143714381439*psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get sta_info */1440if (*psta == NULL) {1441#ifdef DBG_RX_DROP_FRAME1442RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" can't get psta under WIFI_MP_STATE ; drop pkt\n"1443, FUNC_ADPT_ARG(adapter));1444#endif1445ret = _FAIL;1446goto exit;1447}144814491450} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) {1451/* Special case */1452ret = RTW_RX_HANDLED;1453goto exit;1454} else {1455if (_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && (!bmcast)) {1456*psta = rtw_get_stainfo(pstapriv, pattrib->ta);1457if (*psta == NULL) {14581459/* for AP multicast issue , modify by yiwei */1460static systime send_issue_deauth_time = 0;14611462/* RTW_INFO("After send deauth , %u ms has elapsed.\n", rtw_get_passing_time_ms(send_issue_deauth_time)); */14631464if (rtw_get_passing_time_ms(send_issue_deauth_time) > 10000 || send_issue_deauth_time == 0) {1465send_issue_deauth_time = rtw_get_current_time();14661467RTW_INFO("issue_deauth to the ap=" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->bssid));14681469issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);1470}1471}1472}14731474ret = _FAIL;1475#ifdef DBG_RX_DROP_FRAME1476RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" fw_state:0x%x\n"1477, FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));1478#endif1479}14801481exit:148214831484return ret;14851486}14871488sint sta2ap_data_frame(1489_adapter *adapter,1490union recv_frame *precv_frame,1491struct sta_info **psta)1492{1493u8 *ptr = precv_frame->u.hdr.rx_data;1494struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;1495struct sta_priv *pstapriv = &adapter->stapriv;1496struct mlme_priv *pmlmepriv = &adapter->mlmepriv;1497unsigned char *mybssid = get_bssid(pmlmepriv);1498sint ret = _SUCCESS;149915001501if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) {1502/* For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR */1503if (!_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN)) {1504ret = _FAIL;1505goto exit;1506}15071508*psta = rtw_get_stainfo(pstapriv, pattrib->ta);1509if (*psta == NULL) {1510if (!IS_RADAR_DETECTED(adapter_to_rfctl(adapter))) {1511#ifndef CONFIG_CUSTOMER_ALIBABA_GENERAL1512RTW_INFO("issue_deauth to sta=" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->src));1513issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);1514#endif1515}15161517ret = RTW_RX_HANDLED;1518goto exit;1519}15201521process_pwrbit_data(adapter, precv_frame, *psta);15221523if ((get_frame_sub_type(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE)1524process_wmmps_data(adapter, precv_frame, *psta);15251526if (get_frame_sub_type(ptr) & BIT(6)) {1527/* No data, will not indicate to upper layer, temporily count it here */1528count_rx_stats(adapter, precv_frame, *psta);1529ret = RTW_RX_HANDLED;1530goto exit;1531}1532} else if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE) &&1533(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)) {1534/* RTW_INFO("%s ,in WIFI_MP_STATE\n",__func__); */1535_rtw_memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);1536_rtw_memcpy(pattrib->src, get_addr2_ptr(ptr), ETH_ALEN);1537_rtw_memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);1538_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);1539_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);154015411542*psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get sta_info */1543if (*psta == NULL) {1544#ifdef DBG_RX_DROP_FRAME1545RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" can't get psta under WIFI_MP_STATE ; drop pkt\n"1546, FUNC_ADPT_ARG(adapter));1547#endif1548ret = _FAIL;1549goto exit;1550}15511552} else {1553u8 *myhwaddr = adapter_mac_addr(adapter);1554if (!_rtw_memcmp(pattrib->ra, myhwaddr, ETH_ALEN)) {1555ret = RTW_RX_HANDLED;1556goto exit;1557}1558#ifndef CONFIG_CUSTOMER_ALIBABA_GENERAL1559RTW_INFO("issue_deauth to sta=" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->src));1560issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);1561#endif1562ret = RTW_RX_HANDLED;1563goto exit;1564}15651566exit:156715681569return ret;15701571}15721573sint validate_recv_ctrl_frame(_adapter *padapter, union recv_frame *precv_frame);1574sint validate_recv_ctrl_frame(_adapter *padapter, union recv_frame *precv_frame)1575{1576struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;1577struct sta_priv *pstapriv = &padapter->stapriv;1578u8 *pframe = precv_frame->u.hdr.rx_data;1579struct sta_info *psta = NULL;1580/* uint len = precv_frame->u.hdr.len; */15811582/* RTW_INFO("+validate_recv_ctrl_frame\n"); */15831584if (GetFrameType(pframe) != WIFI_CTRL_TYPE)1585return _FAIL;15861587/* receive the frames that ra(a1) is my address */1588if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_mac_addr(padapter), ETH_ALEN))1589return _FAIL;15901591psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));1592if (psta == NULL)1593return _FAIL;15941595/* for rx pkt statistics */1596psta->sta_stats.last_rx_time = rtw_get_current_time();1597psta->sta_stats.rx_ctrl_pkts++;15981599/* only handle ps-poll */1600if (get_frame_sub_type(pframe) == WIFI_PSPOLL) {1601#ifdef CONFIG_AP_MODE1602u16 aid;1603u8 wmmps_ac = 0;16041605aid = GetAid(pframe);1606if (psta->cmn.aid != aid)1607return _FAIL;16081609switch (pattrib->priority) {1610case 1:1611case 2:1612wmmps_ac = psta->uapsd_bk & BIT(0);1613break;1614case 4:1615case 5:1616wmmps_ac = psta->uapsd_vi & BIT(0);1617break;1618case 6:1619case 7:1620wmmps_ac = psta->uapsd_vo & BIT(0);1621break;1622case 0:1623case 3:1624default:1625wmmps_ac = psta->uapsd_be & BIT(0);1626break;1627}16281629if (wmmps_ac)1630return _FAIL;16311632if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {1633RTW_INFO("%s alive check-rx ps-poll\n", __func__);1634psta->expire_to = pstapriv->expire_to;1635psta->state ^= WIFI_STA_ALIVE_CHK_STATE;1636}16371638if ((psta->state & WIFI_SLEEP_STATE) && (rtw_tim_map_is_set(padapter, pstapriv->sta_dz_bitmap, psta->cmn.aid))) {1639_irqL irqL;1640_list *xmitframe_plist, *xmitframe_phead;1641struct xmit_frame *pxmitframe = NULL;1642struct xmit_priv *pxmitpriv = &padapter->xmitpriv;16431644/* _enter_critical_bh(&psta->sleep_q.lock, &irqL); */1645_enter_critical_bh(&pxmitpriv->lock, &irqL);16461647xmitframe_phead = get_list_head(&psta->sleep_q);1648xmitframe_plist = get_next(xmitframe_phead);16491650if ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) {1651pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);16521653xmitframe_plist = get_next(xmitframe_plist);16541655rtw_list_delete(&pxmitframe->list);16561657psta->sleepq_len--;16581659if (psta->sleepq_len > 0)1660pxmitframe->attrib.mdata = 1;1661else1662pxmitframe->attrib.mdata = 0;16631664pxmitframe->attrib.triggered = 1;16651666/* RTW_INFO("handling ps-poll, q_len=%d\n", psta->sleepq_len); */1667/* RTW_INFO_DUMP("handling, tim=", pstapriv->tim_bitmap, pstapriv->aid_bmp_len); */16681669#if 01670_exit_critical_bh(&psta->sleep_q.lock, &irqL);1671if (rtw_hal_xmit(padapter, pxmitframe) == _TRUE)1672rtw_os_xmit_complete(padapter, pxmitframe);1673_enter_critical_bh(&psta->sleep_q.lock, &irqL);1674#endif1675rtw_hal_xmitframe_enqueue(padapter, pxmitframe);16761677if (psta->sleepq_len == 0) {1678rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, psta->cmn.aid);16791680/* RTW_INFO("after handling ps-poll\n"); */1681/* RTW_INFO_DUMP("after handling, tim=", pstapriv->tim_bitmap, pstapriv->aid_bmp_len); */16821683/* upate BCN for TIM IE */1684/* update_BCNTIM(padapter); */1685update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0);1686}16871688/* _exit_critical_bh(&psta->sleep_q.lock, &irqL); */1689_exit_critical_bh(&pxmitpriv->lock, &irqL);16901691} else {1692/* _exit_critical_bh(&psta->sleep_q.lock, &irqL); */1693_exit_critical_bh(&pxmitpriv->lock, &irqL);16941695/* RTW_INFO("no buffered packets to xmit\n"); */1696if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, psta->cmn.aid)) {1697if (psta->sleepq_len == 0) {1698RTW_INFO("no buffered packets to xmit\n");16991700/* issue nulldata with More data bit = 0 to indicate we have no buffered packets */1701issue_nulldata(padapter, psta->cmn.mac_addr, 0, 0, 0);1702} else {1703RTW_INFO("error!psta->sleepq_len=%d\n", psta->sleepq_len);1704psta->sleepq_len = 0;1705}17061707rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, psta->cmn.aid);17081709/* upate BCN for TIM IE */1710/* update_BCNTIM(padapter); */1711update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0);1712}1713}1714}1715#endif /* CONFIG_AP_MODE */1716} else if (get_frame_sub_type(pframe) == WIFI_NDPA) {1717#ifdef CONFIG_BEAMFORMING1718rtw_beamforming_get_ndpa_frame(padapter, precv_frame);1719#endif/*CONFIG_BEAMFORMING*/1720} else if (get_frame_sub_type(pframe) == WIFI_BAR) {1721rtw_process_bar_frame(padapter, precv_frame);1722}17231724return _FAIL;17251726}17271728#if defined(CONFIG_IEEE80211W) || defined(CONFIG_RTW_MESH)1729static sint validate_mgmt_protect(_adapter *adapter, union recv_frame *precv_frame)1730{1731#define DBG_VALIDATE_MGMT_PROTECT 01732#define DBG_VALIDATE_MGMT_DEC 017331734struct security_priv *sec = &adapter->securitypriv;1735struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;1736struct sta_info *psta = precv_frame->u.hdr.psta;1737u8 *ptr;1738u8 type;1739u8 subtype;1740u8 is_bmc;1741u8 category = 0xFF;17421743#ifdef CONFIG_IEEE80211W1744const u8 *igtk;1745u16 igtk_id;1746u64* ipn;1747#endif17481749u8 *mgmt_DATA;1750u32 data_len = 0;17511752sint ret;17531754#ifdef CONFIG_RTW_MESH1755if (MLME_IS_MESH(adapter)) {1756if (!adapter->mesh_info.mesh_auth_id)1757return pattrib->privacy ? _FAIL : _SUCCESS;1758} else1759#endif1760if (SEC_IS_BIP_KEY_INSTALLED(sec) == _FALSE)1761return _SUCCESS;17621763ptr = precv_frame->u.hdr.rx_data;1764type = GetFrameType(ptr);1765subtype = get_frame_sub_type(ptr); /* bit(7)~bit(2) */1766is_bmc = IS_MCAST(GetAddr1Ptr(ptr));17671768#if DBG_VALIDATE_MGMT_PROTECT1769if (subtype == WIFI_DEAUTH) {1770RTW_INFO(FUNC_ADPT_FMT" bmc:%u, deauth, privacy:%u, encrypt:%u, bdecrypted:%u\n"1771, FUNC_ADPT_ARG(adapter)1772, is_bmc, pattrib->privacy, pattrib->encrypt, pattrib->bdecrypted);1773} else if (subtype == WIFI_DISASSOC) {1774RTW_INFO(FUNC_ADPT_FMT" bmc:%u, disassoc, privacy:%u, encrypt:%u, bdecrypted:%u\n"1775, FUNC_ADPT_ARG(adapter)1776, is_bmc, pattrib->privacy, pattrib->encrypt, pattrib->bdecrypted);1777} if (subtype == WIFI_ACTION) {1778if (pattrib->privacy) {1779RTW_INFO(FUNC_ADPT_FMT" bmc:%u, action(?), privacy:%u, encrypt:%u, bdecrypted:%u\n"1780, FUNC_ADPT_ARG(adapter)1781, is_bmc, pattrib->privacy, pattrib->encrypt, pattrib->bdecrypted);1782} else {1783RTW_INFO(FUNC_ADPT_FMT" bmc:%u, action(%u), privacy:%u, encrypt:%u, bdecrypted:%u\n"1784, FUNC_ADPT_ARG(adapter), is_bmc1785, *(ptr + sizeof(struct rtw_ieee80211_hdr_3addr))1786, pattrib->privacy, pattrib->encrypt, pattrib->bdecrypted);1787}1788}1789#endif17901791if (!pattrib->privacy) {1792if (!psta || !(psta->flags & WLAN_STA_MFP)) {1793/* peer is not MFP capable, no need to check */1794goto exit;1795}17961797if (subtype == WIFI_ACTION)1798category = *(ptr + sizeof(struct rtw_ieee80211_hdr_3addr));17991800if (is_bmc) {1801/* broadcast cases */1802if (subtype == WIFI_ACTION) {1803if (CATEGORY_IS_GROUP_PRIVACY(category)) {1804/* drop broadcast group privacy action frame without encryption */1805#if DBG_VALIDATE_MGMT_PROTECT1806RTW_INFO(FUNC_ADPT_FMT" broadcast gp action(%u) w/o encrypt\n"1807, FUNC_ADPT_ARG(adapter), category);1808#endif1809goto fail;1810}1811if (CATEGORY_IS_ROBUST(category)) {1812/* broadcast robust action frame need BIP check */1813goto bip_verify;1814}1815}1816if (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC) {1817/* broadcast deauth or disassoc frame need BIP check */1818goto bip_verify;1819}1820goto exit;18211822} else {1823/* unicast cases */1824#ifdef CONFIG_IEEE80211W1825if (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC) {1826if (!MLME_IS_MESH(adapter)) {1827unsigned short reason = le16_to_cpu(*(unsigned short *)(ptr + WLAN_HDR_A3_LEN));18281829#if DBG_VALIDATE_MGMT_PROTECT1830RTW_INFO(FUNC_ADPT_FMT" unicast %s, reason=%d w/o encrypt\n"1831, FUNC_ADPT_ARG(adapter), subtype == WIFI_DEAUTH ? "deauth" : "disassoc", reason);1832#endif1833if (reason == 6 || reason == 7) {1834/* issue sa query request */1835issue_action_SA_Query(adapter, psta->cmn.mac_addr, 0, 0, IEEE80211W_RIGHT_KEY);1836}1837}1838goto fail;1839}1840#endif18411842if (subtype == WIFI_ACTION && CATEGORY_IS_ROBUST(category)) {1843if (psta->bpairwise_key_installed == _TRUE) {1844#if DBG_VALIDATE_MGMT_PROTECT1845RTW_INFO(FUNC_ADPT_FMT" unicast robust action(%d) w/o encrypt\n"1846, FUNC_ADPT_ARG(adapter), category);1847#endif1848goto fail;1849}1850}1851goto exit;1852}18531854bip_verify:1855#ifdef CONFIG_IEEE80211W1856#ifdef CONFIG_RTW_MESH1857if (MLME_IS_MESH(adapter)) {1858if (psta->igtk_bmp) {1859igtk = psta->igtk.skey;1860igtk_id = psta->igtk_id;1861ipn = &psta->igtk_pn.val;1862} else {1863/* mesh MFP without IGTK */1864goto exit;1865}1866} else1867#endif1868{1869igtk = sec->dot11wBIPKey[sec->dot11wBIPKeyid].skey;1870igtk_id = sec->dot11wBIPKeyid;1871ipn = &sec->dot11wBIPrxpn.val;1872}18731874/* verify BIP MME IE */1875ret = rtw_BIP_verify(adapter1876, get_recvframe_data(precv_frame)1877, get_recvframe_len(precv_frame)1878, igtk, igtk_id, ipn);1879if (ret == _FAIL) {1880/* RTW_INFO("802.11w BIP verify fail\n"); */1881goto fail;18821883} else if (ret == RTW_RX_HANDLED) {1884#if DBG_VALIDATE_MGMT_PROTECT1885RTW_INFO(FUNC_ADPT_FMT" none protected packet\n", FUNC_ADPT_ARG(adapter));1886#endif1887goto fail;1888}1889#endif /* CONFIG_IEEE80211W */1890goto exit;1891}18921893/* cases to decrypt mgmt frame */1894pattrib->bdecrypted = 0;1895pattrib->encrypt = _AES_;1896pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);18971898/* set iv and icv length */1899SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt);1900_rtw_memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);1901_rtw_memcpy(pattrib->ta, get_addr2_ptr(ptr), ETH_ALEN);19021903/* actual management data frame body */1904data_len = pattrib->pkt_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len;1905mgmt_DATA = rtw_zmalloc(data_len);1906if (mgmt_DATA == NULL) {1907RTW_INFO(FUNC_ADPT_FMT" mgmt allocate fail !!!!!!!!!\n", FUNC_ADPT_ARG(adapter));1908goto fail;1909}19101911#if DBG_VALIDATE_MGMT_DEC1912/* dump the packet content before decrypt */1913{1914int pp;19151916printk("pattrib->pktlen = %d =>", pattrib->pkt_len);1917for (pp = 0; pp < pattrib->pkt_len; pp++)1918printk(" %02x ", ptr[pp]);1919printk("\n");1920}1921#endif19221923precv_frame = decryptor(adapter, precv_frame);1924/* save actual management data frame body */1925_rtw_memcpy(mgmt_DATA, ptr + pattrib->hdrlen + pattrib->iv_len, data_len);1926/* overwrite the iv field */1927_rtw_memcpy(ptr + pattrib->hdrlen, mgmt_DATA, data_len);1928/* remove the iv and icv length */1929pattrib->pkt_len = pattrib->pkt_len - pattrib->iv_len - pattrib->icv_len;1930rtw_mfree(mgmt_DATA, data_len);19311932#if DBG_VALIDATE_MGMT_DEC1933/* print packet content after decryption */1934{1935int pp;19361937printk("after decryption pattrib->pktlen = %d @@=>", pattrib->pkt_len);1938for (pp = 0; pp < pattrib->pkt_len; pp++)1939printk(" %02x ", ptr[pp]);1940printk("\n");1941}1942#endif19431944if (!precv_frame) {1945#if DBG_VALIDATE_MGMT_PROTECT1946RTW_INFO(FUNC_ADPT_FMT" mgmt descrypt fail !!!!!!!!!\n", FUNC_ADPT_ARG(adapter));1947#endif1948goto fail;1949}19501951exit:1952return _SUCCESS;19531954fail:1955return _FAIL;19561957}1958#endif /* defined(CONFIG_IEEE80211W) || defined(CONFIG_RTW_MESH) */19591960union recv_frame *recvframe_chk_defrag(PADAPTER padapter, union recv_frame *precv_frame);19611962sint validate_recv_mgnt_frame(PADAPTER padapter, union recv_frame *precv_frame)1963{1964struct sta_info *psta = precv_frame->u.hdr.psta1965= rtw_get_stainfo(&padapter->stapriv, get_addr2_ptr(precv_frame->u.hdr.rx_data));19661967#if defined(CONFIG_IEEE80211W) || defined(CONFIG_RTW_MESH)1968if (validate_mgmt_protect(padapter, precv_frame) == _FAIL) {1969DBG_COUNTER(padapter->rx_logs.core_rx_pre_mgmt_err_80211w);1970goto exit;1971}1972#endif19731974precv_frame = recvframe_chk_defrag(padapter, precv_frame);1975if (precv_frame == NULL)1976return _SUCCESS;19771978/* for rx pkt statistics */1979if (psta) {1980psta->sta_stats.last_rx_time = rtw_get_current_time();1981psta->sta_stats.rx_mgnt_pkts++;1982if (get_frame_sub_type(precv_frame->u.hdr.rx_data) == WIFI_BEACON)1983psta->sta_stats.rx_beacon_pkts++;1984else if (get_frame_sub_type(precv_frame->u.hdr.rx_data) == WIFI_PROBEREQ)1985psta->sta_stats.rx_probereq_pkts++;1986else if (get_frame_sub_type(precv_frame->u.hdr.rx_data) == WIFI_PROBERSP) {1987if (_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(precv_frame->u.hdr.rx_data), ETH_ALEN) == _TRUE)1988psta->sta_stats.rx_probersp_pkts++;1989else if (is_broadcast_mac_addr(GetAddr1Ptr(precv_frame->u.hdr.rx_data))1990|| is_multicast_mac_addr(GetAddr1Ptr(precv_frame->u.hdr.rx_data)))1991psta->sta_stats.rx_probersp_bm_pkts++;1992else1993psta->sta_stats.rx_probersp_uo_pkts++;1994}1995}19961997mgt_dispatcher(padapter, precv_frame);19981999#if defined(CONFIG_IEEE80211W) || defined(CONFIG_RTW_MESH)2000exit:2001#endif2002return _SUCCESS;20032004}20052006sint validate_recv_data_frame(_adapter *adapter, union recv_frame *precv_frame)2007{2008u8 bretry, a4_shift;2009struct sta_info *psta = NULL;2010u8 *ptr = precv_frame->u.hdr.rx_data;2011struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;2012struct security_priv *psecuritypriv = &adapter->securitypriv;2013sint ret = _SUCCESS;20142015bretry = GetRetry(ptr);2016a4_shift = (pattrib->to_fr_ds == 3) ? ETH_ALEN : 0;20172018/* some address fields are different when using AMSDU */2019if (pattrib->qos)2020pattrib->amsdu = GetAMsdu(ptr + WLAN_HDR_A3_LEN + a4_shift);2021else2022pattrib->amsdu = 0;20232024#ifdef CONFIG_RTW_MESH2025if (MLME_IS_MESH(adapter)) {2026ret = rtw_mesh_rx_data_validate_hdr(adapter, precv_frame, &psta);2027goto pre_validate_status_chk;2028}2029#endif20302031switch (pattrib->to_fr_ds) {2032case 0:2033_rtw_memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);2034_rtw_memcpy(pattrib->ta, get_addr2_ptr(ptr), ETH_ALEN);2035_rtw_memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);2036_rtw_memcpy(pattrib->src, get_addr2_ptr(ptr), ETH_ALEN);2037_rtw_memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);2038ret = sta2sta_data_frame(adapter, precv_frame, &psta);2039break;20402041case 1:2042_rtw_memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);2043_rtw_memcpy(pattrib->ta, get_addr2_ptr(ptr), ETH_ALEN);2044_rtw_memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);2045_rtw_memcpy(pattrib->src, GetAddr3Ptr(ptr), ETH_ALEN);2046_rtw_memcpy(pattrib->bssid, get_addr2_ptr(ptr), ETH_ALEN);2047ret = ap2sta_data_frame(adapter, precv_frame, &psta);2048break;20492050case 2:2051_rtw_memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);2052_rtw_memcpy(pattrib->ta, get_addr2_ptr(ptr), ETH_ALEN);2053_rtw_memcpy(pattrib->dst, GetAddr3Ptr(ptr), ETH_ALEN);2054_rtw_memcpy(pattrib->src, get_addr2_ptr(ptr), ETH_ALEN);2055_rtw_memcpy(pattrib->bssid, GetAddr1Ptr(ptr), ETH_ALEN);2056ret = sta2ap_data_frame(adapter, precv_frame, &psta);2057break;20582059case 3:2060default:2061/* WDS is not supported */2062ret = _FAIL;2063break;2064}20652066#ifdef CONFIG_RTW_MESH2067pre_validate_status_chk:2068#endif2069if (ret == _FAIL) {2070#ifdef DBG_RX_DROP_FRAME2071RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" case:%d, res:%d, ra="MAC_FMT", ta="MAC_FMT"\n"2072, FUNC_ADPT_ARG(adapter), pattrib->to_fr_ds, ret, MAC_ARG(GetAddr1Ptr(ptr)), MAC_ARG(get_addr2_ptr(ptr)));2073#endif2074goto exit;2075} else if (ret == RTW_RX_HANDLED)2076goto exit;207720782079if (psta == NULL) {2080#ifdef DBG_RX_DROP_FRAME2081RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" psta == NULL, ra="MAC_FMT", ta="MAC_FMT"\n"2082, FUNC_ADPT_ARG(adapter), MAC_ARG(GetAddr1Ptr(ptr)), MAC_ARG(get_addr2_ptr(ptr)));2083#endif2084ret = _FAIL;2085goto exit;2086}20872088precv_frame->u.hdr.psta = psta;2089precv_frame->u.hdr.preorder_ctrl = NULL;2090pattrib->ack_policy = 0;20912092/* parsing QC field */2093if (pattrib->qos == 1) {2094pattrib->priority = GetPriority((ptr + WLAN_HDR_A3_LEN + a4_shift)); /* point to Qos field*/2095pattrib->ack_policy = GetAckpolicy((ptr + WLAN_HDR_A3_LEN + a4_shift));2096pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN + a4_shift;2097if (pattrib->priority != 0 && pattrib->priority != 3)2098adapter->recvpriv.is_any_non_be_pkts = _TRUE;2099else2100adapter->recvpriv.is_any_non_be_pkts = _FALSE;2101} else {2102pattrib->priority = 0;2103pattrib->hdrlen = WLAN_HDR_A3_LEN + a4_shift;2104}21052106if (pattrib->order) /* HT-CTRL 11n */2107pattrib->hdrlen += 4;21082109/* decache, drop duplicate recv packets */2110ret = recv_decache(precv_frame);2111if (ret == _FAIL)2112goto exit;21132114if (!IS_MCAST(pattrib->ra)) {21152116if (pattrib->qos)2117precv_frame->u.hdr.preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority];21182119if (recv_ucast_pn_decache(precv_frame) == _FAIL) {2120#ifdef DBG_RX_DROP_FRAME2121RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" recv_ucast_pn_decache return _FAIL for sta="MAC_FMT"\n"2122, FUNC_ADPT_ARG(adapter), MAC_ARG(psta->cmn.mac_addr));2123#endif2124ret = _FAIL;2125goto exit;2126}2127} else {2128if (recv_bcast_pn_decache(precv_frame) == _FAIL) {2129#ifdef DBG_RX_DROP_FRAME2130RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" recv_bcast_pn_decache return _FAIL for sta="MAC_FMT"\n"2131, FUNC_ADPT_ARG(adapter), MAC_ARG(psta->cmn.mac_addr));2132#endif2133ret = _FAIL;2134goto exit;2135}2136}21372138if (pattrib->privacy) {2139#ifdef CONFIG_TDLS2140if ((psta->tdls_sta_state & TDLS_LINKED_STATE) && (psta->dot118021XPrivacy == _AES_))2141pattrib->encrypt = psta->dot118021XPrivacy;2142else2143#endif /* CONFIG_TDLS */2144GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, IS_MCAST(pattrib->ra));214521462147SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt);2148} else {2149pattrib->encrypt = 0;2150pattrib->iv_len = pattrib->icv_len = 0;2151}21522153#ifdef CONFIG_RTW_MESH2154if (!pattrib->amsdu2155&& pattrib->mesh_ctrl_present2156&& (!pattrib->encrypt || pattrib->bdecrypted))2157ret = rtw_mesh_rx_validate_mctrl_non_amsdu(adapter, precv_frame);2158#endif21592160exit:2161return ret;2162}21632164static inline void dump_rx_packet(u8 *ptr)2165{2166int i;21672168RTW_INFO("#############################\n");2169for (i = 0; i < 64; i = i + 8)2170RTW_INFO("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr + i),2171*(ptr + i + 1), *(ptr + i + 2) , *(ptr + i + 3) , *(ptr + i + 4), *(ptr + i + 5), *(ptr + i + 6), *(ptr + i + 7));2172RTW_INFO("#############################\n");2173}21742175sint validate_recv_frame(_adapter *adapter, union recv_frame *precv_frame);2176sint validate_recv_frame(_adapter *adapter, union recv_frame *precv_frame)2177{2178/* shall check frame subtype, to / from ds, da, bssid */21792180/* then call check if rx seq/frag. duplicated. */21812182u8 type;2183u8 subtype;2184sint retval = _SUCCESS;21852186struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;2187struct recv_priv *precvpriv = &adapter->recvpriv;21882189u8 *ptr = precv_frame->u.hdr.rx_data;2190u8 ver = (unsigned char)(*ptr) & 0x3 ;2191#ifdef CONFIG_FIND_BEST_CHANNEL2192struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);2193struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;2194#endif21952196#ifdef CONFIG_TDLS2197struct tdls_info *ptdlsinfo = &adapter->tdlsinfo;2198#endif /* CONFIG_TDLS */2199#ifdef CONFIG_WAPI_SUPPORT2200PRT_WAPI_T pWapiInfo = &adapter->wapiInfo;2201struct recv_frame_hdr *phdr = &precv_frame->u.hdr;2202u8 wai_pkt = 0;2203u16 sc;2204u8 external_len = 0;2205#endif220622072208#ifdef CONFIG_FIND_BEST_CHANNEL2209if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {2210int ch_set_idx = rtw_chset_search_ch(rfctl->channel_set, rtw_get_oper_ch(adapter));2211if (ch_set_idx >= 0)2212rfctl->channel_set[ch_set_idx].rx_count++;2213}2214#endif22152216#ifdef CONFIG_TDLS2217if (ptdlsinfo->ch_sensing == 1 && ptdlsinfo->cur_channel != 0)2218ptdlsinfo->collect_pkt_num[ptdlsinfo->cur_channel - 1]++;2219#endif /* CONFIG_TDLS */22202221#ifdef RTK_DMP_PLATFORM2222if (0) {2223RTW_INFO("++\n");2224{2225int i;2226for (i = 0; i < 64; i = i + 8)2227RTW_INFO("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:", *(ptr + i),2228*(ptr + i + 1), *(ptr + i + 2) , *(ptr + i + 3) , *(ptr + i + 4), *(ptr + i + 5), *(ptr + i + 6), *(ptr + i + 7));22292230}2231RTW_INFO("--\n");2232}2233#endif /* RTK_DMP_PLATFORM */22342235/* add version chk */2236if (ver != 0) {2237retval = _FAIL;2238DBG_COUNTER(adapter->rx_logs.core_rx_pre_ver_err);2239goto exit;2240}22412242type = GetFrameType(ptr);2243subtype = get_frame_sub_type(ptr); /* bit(7)~bit(2) */22442245pattrib->to_fr_ds = get_tofr_ds(ptr);22462247pattrib->frag_num = GetFragNum(ptr);2248pattrib->seq_num = GetSequence(ptr);22492250pattrib->pw_save = GetPwrMgt(ptr);2251pattrib->mfrag = GetMFrag(ptr);2252pattrib->mdata = GetMData(ptr);2253pattrib->privacy = GetPrivacy(ptr);2254pattrib->order = GetOrder(ptr);2255#ifdef CONFIG_WAPI_SUPPORT2256sc = (pattrib->seq_num << 4) | pattrib->frag_num;2257#endif22582259#if 1 /* Dump rx packets */2260{2261u8 bDumpRxPkt = 0;22622263rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt));2264if (bDumpRxPkt == 1) /* dump all rx packets */2265dump_rx_packet(ptr);2266else if ((bDumpRxPkt == 2) && (type == WIFI_MGT_TYPE))2267dump_rx_packet(ptr);2268else if ((bDumpRxPkt == 3) && (type == WIFI_DATA_TYPE))2269dump_rx_packet(ptr);2270}2271#endif2272switch (type) {2273case WIFI_MGT_TYPE: /* mgnt */2274DBG_COUNTER(adapter->rx_logs.core_rx_pre_mgmt);2275retval = validate_recv_mgnt_frame(adapter, precv_frame);2276if (retval == _FAIL) {2277DBG_COUNTER(adapter->rx_logs.core_rx_pre_mgmt_err);2278}2279retval = _FAIL; /* only data frame return _SUCCESS */2280break;2281case WIFI_CTRL_TYPE: /* ctrl */2282DBG_COUNTER(adapter->rx_logs.core_rx_pre_ctrl);2283retval = validate_recv_ctrl_frame(adapter, precv_frame);2284if (retval == _FAIL) {2285DBG_COUNTER(adapter->rx_logs.core_rx_pre_ctrl_err);2286}2287retval = _FAIL; /* only data frame return _SUCCESS */2288break;2289case WIFI_DATA_TYPE: /* data */2290DBG_COUNTER(adapter->rx_logs.core_rx_pre_data);2291#ifdef CONFIG_WAPI_SUPPORT2292if (pattrib->qos)2293external_len = 2;2294else2295external_len = 0;22962297wai_pkt = rtw_wapi_is_wai_packet(adapter, ptr);22982299phdr->bIsWaiPacket = wai_pkt;23002301if (wai_pkt != 0) {2302if (sc != adapter->wapiInfo.wapiSeqnumAndFragNum)2303adapter->wapiInfo.wapiSeqnumAndFragNum = sc;2304else {2305retval = _FAIL;2306DBG_COUNTER(adapter->rx_logs.core_rx_pre_data_wapi_seq_err);2307break;2308}2309} else {23102311if (rtw_wapi_drop_for_key_absent(adapter, get_addr2_ptr(ptr))) {2312retval = _FAIL;2313WAPI_TRACE(WAPI_RX, "drop for key absent for rx\n");2314DBG_COUNTER(adapter->rx_logs.core_rx_pre_data_wapi_key_err);2315break;2316}2317}23182319#endif23202321pattrib->qos = (subtype & BIT(7)) ? 1 : 0;2322retval = validate_recv_data_frame(adapter, precv_frame);2323if (retval == _FAIL) {2324precvpriv->dbg_rx_drop_count++;2325DBG_COUNTER(adapter->rx_logs.core_rx_pre_data_err);2326} else if (retval == _SUCCESS) {2327#ifdef DBG_RX_DUMP_EAP2328if (!pattrib->encrypt || pattrib->bdecrypted) {2329u8 bDumpRxPkt;2330u16 eth_type;23312332/* dump eapol */2333rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt));2334/* get ether_type */2335_rtw_memcpy(ð_type, ptr + pattrib->hdrlen + pattrib->iv_len + RATTRIB_GET_MCTRL_LEN(pattrib) + LLC_HEADER_SIZE, 2);2336eth_type = ntohs((unsigned short) eth_type);2337if ((bDumpRxPkt == 4) && (eth_type == 0x888e))2338dump_rx_packet(ptr);2339}2340#endif2341} else2342DBG_COUNTER(adapter->rx_logs.core_rx_pre_data_handled);2343break;2344default:2345DBG_COUNTER(adapter->rx_logs.core_rx_pre_unknown);2346#ifdef DBG_RX_DROP_FRAME2347RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" fail! type=0x%x\n"2348, FUNC_ADPT_ARG(adapter), type);2349#endif2350retval = _FAIL;2351break;2352}23532354exit:235523562357return retval;2358}235923602361/* remove the wlanhdr and add the eth_hdr */2362sint wlanhdr_to_ethhdr(union recv_frame *precvframe)2363{2364sint rmv_len;2365u16 eth_type, len;2366u8 bsnaphdr;2367u8 *psnap_type;2368struct ieee80211_snap_hdr *psnap;23692370sint ret = _SUCCESS;2371_adapter *adapter = precvframe->u.hdr.adapter;2372struct mlme_priv *pmlmepriv = &adapter->mlmepriv;23732374u8 *ptr = get_recvframe_data(precvframe) ; /* point to frame_ctrl field */2375struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;237623772378if (pattrib->encrypt)2379recvframe_pull_tail(precvframe, pattrib->icv_len);23802381psnap = (struct ieee80211_snap_hdr *)(ptr + pattrib->hdrlen + pattrib->iv_len + RATTRIB_GET_MCTRL_LEN(pattrib));2382psnap_type = ptr + pattrib->hdrlen + pattrib->iv_len + RATTRIB_GET_MCTRL_LEN(pattrib) + SNAP_SIZE;2383/* convert hdr + possible LLC headers into Ethernet header */2384/* eth_type = (psnap_type[0] << 8) | psnap_type[1]; */2385if ((_rtw_memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) &&2386(_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) == _FALSE) &&2387(_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_AARP, 2) == _FALSE)) ||2388/* eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || */2389_rtw_memcmp(psnap, rtw_bridge_tunnel_header, SNAP_SIZE)) {2390/* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */2391bsnaphdr = _TRUE;2392} else {2393/* Leave Ethernet header part of hdr and full payload */2394bsnaphdr = _FALSE;2395}23962397rmv_len = pattrib->hdrlen + pattrib->iv_len + RATTRIB_GET_MCTRL_LEN(pattrib) + (bsnaphdr ? SNAP_SIZE : 0);2398len = precvframe->u.hdr.len - rmv_len;239924002401_rtw_memcpy(ð_type, ptr + rmv_len, 2);2402eth_type = ntohs((unsigned short)eth_type); /* pattrib->ether_type */2403pattrib->eth_type = eth_type;240424052406if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE)) {2407ptr += rmv_len ;2408*ptr = 0x87;2409*(ptr + 1) = 0x12;24102411eth_type = 0x8712;2412/* append rx status for mp test packets */2413ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + 2) - 24);2414if (!ptr) {2415ret = _FAIL;2416goto exiting;2417}2418_rtw_memcpy(ptr, get_rxmem(precvframe), 24);2419ptr += 24;2420} else {2421ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0)));2422if (!ptr) {2423ret = _FAIL;2424goto exiting;2425}2426}24272428if (ptr) {2429_rtw_memcpy(ptr, pattrib->dst, ETH_ALEN);2430_rtw_memcpy(ptr + ETH_ALEN, pattrib->src, ETH_ALEN);24312432if (!bsnaphdr) {2433len = htons(len);2434_rtw_memcpy(ptr + 12, &len, 2);2435}24362437rtw_rframe_set_os_pkt(precvframe);2438}24392440exiting:2441return ret;24422443}24442445#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)2446#ifndef CONFIG_SDIO_RX_COPY2447#ifdef PLATFORM_LINUX2448static void recvframe_expand_pkt(2449PADAPTER padapter,2450union recv_frame *prframe)2451{2452struct recv_frame_hdr *pfhdr;2453_pkt *ppkt;2454u8 shift_sz;2455u32 alloc_sz;2456u8 *ptr;245724582459pfhdr = &prframe->u.hdr;24602461/* 6 is for IP header 8 bytes alignment in QoS packet case. */2462if (pfhdr->attrib.qos)2463shift_sz = 6;2464else2465shift_sz = 0;24662467/* for first fragment packet, need to allocate */2468/* (1536 + RXDESC_SIZE + drvinfo_sz) to reassemble packet */2469/* 8 is for skb->data 8 bytes alignment.2470* alloc_sz = _RND(1536 + RXDESC_SIZE + pfhdr->attrib.drvinfosize + shift_sz + 8, 128); */2471alloc_sz = 1664; /* round (1536 + 24 + 32 + shift_sz + 8) to 128 bytes alignment */24722473/* 3 1. alloc new skb */2474/* prepare extra space for 4 bytes alignment */2475ppkt = rtw_skb_alloc(alloc_sz);24762477if (!ppkt)2478return; /* no way to expand */24792480/* 3 2. Prepare new skb to replace & release old skb */2481/* force ppkt->data at 8-byte alignment address */2482skb_reserve(ppkt, 8 - ((SIZE_PTR)ppkt->data & 7));2483/* force ip_hdr at 8-byte alignment address according to shift_sz */2484skb_reserve(ppkt, shift_sz);24852486/* copy data to new pkt */2487ptr = skb_put(ppkt, pfhdr->len);2488if (ptr)2489_rtw_memcpy(ptr, pfhdr->rx_data, pfhdr->len);24902491rtw_skb_free(pfhdr->pkt);24922493/* attach new pkt to recvframe */2494pfhdr->pkt = ppkt;2495pfhdr->rx_head = ppkt->head;2496pfhdr->rx_data = ppkt->data;2497pfhdr->rx_tail = skb_tail_pointer(ppkt);2498pfhdr->rx_end = skb_end_pointer(ppkt);2499}2500#else /*!= PLATFORM_LINUX*/2501#warning "recvframe_expand_pkt not implement, defrag may crash system"2502#endif2503#endif /*#ifndef CONFIG_SDIO_RX_COPY*/2504#endif25052506/* perform defrag */2507union recv_frame *recvframe_defrag(_adapter *adapter, _queue *defrag_q);2508union recv_frame *recvframe_defrag(_adapter *adapter, _queue *defrag_q)2509{2510_list *plist, *phead;2511u8 *data, wlanhdr_offset;2512u8 curfragnum;2513struct recv_frame_hdr *pfhdr, *pnfhdr;2514union recv_frame *prframe, *pnextrframe;2515_queue *pfree_recv_queue;251625172518curfragnum = 0;2519pfree_recv_queue = &adapter->recvpriv.free_recv_queue;25202521phead = get_list_head(defrag_q);2522plist = get_next(phead);2523prframe = LIST_CONTAINOR(plist, union recv_frame, u);2524pfhdr = &prframe->u.hdr;2525rtw_list_delete(&(prframe->u.list));25262527if (curfragnum != pfhdr->attrib.frag_num) {2528/* the first fragment number must be 0 */2529/* free the whole queue */2530rtw_free_recvframe(prframe, pfree_recv_queue);2531rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);25322533return NULL;2534}25352536#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)2537#ifndef CONFIG_SDIO_RX_COPY2538recvframe_expand_pkt(adapter, prframe);2539#endif2540#endif25412542curfragnum++;25432544plist = get_list_head(defrag_q);25452546plist = get_next(plist);25472548data = get_recvframe_data(prframe);25492550while (rtw_end_of_queue_search(phead, plist) == _FALSE) {2551pnextrframe = LIST_CONTAINOR(plist, union recv_frame , u);2552pnfhdr = &pnextrframe->u.hdr;255325542555/* check the fragment sequence (2nd ~n fragment frame) */25562557if (curfragnum != pnfhdr->attrib.frag_num) {2558/* the fragment number must be increasing (after decache) */2559/* release the defrag_q & prframe */2560rtw_free_recvframe(prframe, pfree_recv_queue);2561rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);2562return NULL;2563}25642565curfragnum++;25662567/* copy the 2nd~n fragment frame's payload to the first fragment */2568/* get the 2nd~last fragment frame's payload */25692570wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;25712572recvframe_pull(pnextrframe, wlanhdr_offset);25732574/* append to first fragment frame's tail (if privacy frame, pull the ICV) */2575recvframe_pull_tail(prframe, pfhdr->attrib.icv_len);25762577/* memcpy */2578_rtw_memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len);25792580recvframe_put(prframe, pnfhdr->len);25812582pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;2583plist = get_next(plist);25842585};25862587/* free the defrag_q queue and return the prframe */2588rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);2589259025912592return prframe;2593}25942595/* check if need to defrag, if needed queue the frame to defrag_q */2596union recv_frame *recvframe_chk_defrag(PADAPTER padapter, union recv_frame *precv_frame)2597{2598u8 ismfrag;2599u8 fragnum;2600u8 *psta_addr;2601struct recv_frame_hdr *pfhdr;2602struct sta_info *psta;2603struct sta_priv *pstapriv;2604_list *phead;2605union recv_frame *prtnframe = NULL;2606_queue *pfree_recv_queue, *pdefrag_q = NULL;260726082609pstapriv = &padapter->stapriv;26102611pfhdr = &precv_frame->u.hdr;26122613pfree_recv_queue = &padapter->recvpriv.free_recv_queue;26142615/* need to define struct of wlan header frame ctrl */2616ismfrag = pfhdr->attrib.mfrag;2617fragnum = pfhdr->attrib.frag_num;26182619psta_addr = pfhdr->attrib.ta;2620psta = rtw_get_stainfo(pstapriv, psta_addr);2621if (psta == NULL) {2622u8 type = GetFrameType(pfhdr->rx_data);2623if (type != WIFI_DATA_TYPE) {2624psta = rtw_get_bcmc_stainfo(padapter);2625if (psta)2626pdefrag_q = &psta->sta_recvpriv.defrag_q;2627} else2628pdefrag_q = NULL;2629} else2630pdefrag_q = &psta->sta_recvpriv.defrag_q;26312632if ((ismfrag == 0) && (fragnum == 0)) {2633prtnframe = precv_frame;/* isn't a fragment frame */2634}26352636if (ismfrag == 1) {2637/* 0~(n-1) fragment frame */2638/* enqueue to defraf_g */2639if (pdefrag_q != NULL) {2640if (fragnum == 0) {2641/* the first fragment */2642if (_rtw_queue_empty(pdefrag_q) == _FALSE) {2643/* free current defrag_q */2644rtw_free_recvframe_queue(pdefrag_q, pfree_recv_queue);2645}2646}264726482649/* Then enqueue the 0~(n-1) fragment into the defrag_q */26502651/* _rtw_spinlock(&pdefrag_q->lock); */2652phead = get_list_head(pdefrag_q);2653rtw_list_insert_tail(&pfhdr->list, phead);2654/* _rtw_spinunlock(&pdefrag_q->lock); */265526562657prtnframe = NULL;26582659} else {2660/* can't find this ta's defrag_queue, so free this recv_frame */2661rtw_free_recvframe(precv_frame, pfree_recv_queue);2662prtnframe = NULL;2663}26642665}26662667if ((ismfrag == 0) && (fragnum != 0)) {2668/* the last fragment frame */2669/* enqueue the last fragment */2670if (pdefrag_q != NULL) {2671/* _rtw_spinlock(&pdefrag_q->lock); */2672phead = get_list_head(pdefrag_q);2673rtw_list_insert_tail(&pfhdr->list, phead);2674/* _rtw_spinunlock(&pdefrag_q->lock); */26752676/* call recvframe_defrag to defrag */2677precv_frame = recvframe_defrag(padapter, pdefrag_q);2678prtnframe = precv_frame;26792680} else {2681/* can't find this ta's defrag_queue, so free this recv_frame */2682rtw_free_recvframe(precv_frame, pfree_recv_queue);2683prtnframe = NULL;2684}26852686}268726882689if ((prtnframe != NULL) && (prtnframe->u.hdr.attrib.privacy)) {2690/* after defrag we must check tkip mic code */2691if (recvframe_chkmic(padapter, prtnframe) == _FAIL) {2692rtw_free_recvframe(prtnframe, pfree_recv_queue);2693prtnframe = NULL;2694}2695}269626972698return prtnframe;26992700}27012702static int rtw_recv_indicatepkt_check(union recv_frame *rframe, u8 *ehdr_pos, u32 pkt_len)2703{2704_adapter *adapter = rframe->u.hdr.adapter;2705struct recv_priv *recvpriv = &adapter->recvpriv;2706struct ethhdr *ehdr = (struct ethhdr *)ehdr_pos;2707#ifdef DBG_IP_R_MONITOR2708int i;2709struct rx_pkt_attrib *pattrib = &rframe->u.hdr.attrib;2710struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;2711struct mlme_priv *pmlmepriv = &adapter->mlmepriv;2712struct wlan_network *cur_network = &(pmlmepriv->cur_network);2713#endif/*DBG_IP_R_MONITOR*/2714int ret = _FAIL;27152716#ifdef CONFIG_WAPI_SUPPORT2717if (rtw_wapi_check_for_drop(adapter, rframe, ehdr_pos)) {2718#ifdef DBG_RX_DROP_FRAME2719RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" rtw_wapi_check_for_drop\n"2720, FUNC_ADPT_ARG(adapter));2721#endif2722goto exit;2723}2724#endif27252726if (rframe->u.hdr.psta)2727rtw_st_ctl_rx(rframe->u.hdr.psta, ehdr_pos);27282729if (ntohs(ehdr->h_proto) == 0x888e)2730parsing_eapol_packet(adapter, ehdr_pos + ETH_HLEN, rframe->u.hdr.psta, 0);2731#ifdef DBG_ARP_DUMP2732else if (ntohs(ehdr->h_proto) == ETH_P_ARP)2733dump_arp_pkt(RTW_DBGDUMP, ehdr->h_dest, ehdr->h_source, ehdr_pos + ETH_HLEN, 0);2734#endif27352736if (recvpriv->sink_udpport > 0)2737rtw_sink_rtp_seq_dbg(adapter, ehdr_pos);27382739#ifdef DBG_UDP_PKT_LOSE_11AC2740#define PAYLOAD_LEN_LOC_OF_IP_HDR 0x10 /*ethernet payload length location of ip header (DA + SA+eth_type+(version&hdr_len)) */27412742if (ntohs(ehdr->h_proto) == ETH_P_ARP) {2743/* ARP Payload length will be 42bytes or 42+18(tailer)=60bytes*/2744if (pkt_len != 42 && pkt_len != 60)2745RTW_INFO("Error !!%s,ARP Payload length %u not correct\n" , __func__ , pkt_len);2746} else if (ntohs(ehdr->h_proto) == ETH_P_IP) {2747if (be16_to_cpu(*((u16 *)(ehdr_pos + PAYLOAD_LEN_LOC_OF_IP_HDR))) != (pkt_len) - ETH_HLEN) {2748RTW_INFO("Error !!%s,Payload length not correct\n" , __func__);2749RTW_INFO("%s, IP header describe Total length=%u\n" , __func__ , be16_to_cpu(*((u16 *)(ehdr_pos + PAYLOAD_LEN_LOC_OF_IP_HDR))));2750RTW_INFO("%s, Pkt real length=%u\n" , __func__ , (pkt_len) - ETH_HLEN);2751}2752}2753#endif27542755#ifdef DBG_IP_R_MONITOR2756#define LEN_ARP_OP_HDR 7 /*ARP OERATION */2757if (ntohs(ehdr->h_proto) == ETH_P_ARP) {27582759if(check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE){2760if(ehdr_pos[ETHERNET_HEADER_SIZE+LEN_ARP_OP_HDR] == 2) {27612762RTW_INFO("%s,[DBG_ARP] Rx ARP RSP Packet;SeqNum = %d !\n",2763__FUNCTION__, pattrib->seq_num);27642765dump_arp_pkt(RTW_DBGDUMP, ehdr->h_dest, ehdr->h_source, ehdr_pos + ETH_HLEN, 0);27662767}2768}2769}2770#endif/*DBG_IP_R_MONITOR*/27712772#ifdef CONFIG_AUTO_AP_MODE2773if (ntohs(ehdr->h_proto) == 0x8899)2774rtw_auto_ap_rx_msg_dump(adapter, rframe, ehdr_pos);2775#endif27762777ret = _SUCCESS;27782779#ifdef CONFIG_WAPI_SUPPORT2780exit:2781#endif2782return ret;2783}27842785#ifdef CONFIG_RTW_MESH2786static void recv_free_fwd_resource(_adapter *adapter, struct xmit_frame *fwd_frame, _list *b2u_list)2787{2788struct xmit_priv *xmitpriv = &adapter->xmitpriv;27892790if (fwd_frame)2791rtw_free_xmitframe(xmitpriv, fwd_frame);27922793#if CONFIG_RTW_MESH_DATA_BMC_TO_UC2794if (!rtw_is_list_empty(b2u_list)) {2795struct xmit_frame *b2uframe;2796_list *list;27972798list = get_next(b2u_list);2799while (rtw_end_of_queue_search(b2u_list, list) == _FALSE) {2800b2uframe = LIST_CONTAINOR(list, struct xmit_frame, list);2801list = get_next(list);2802rtw_list_delete(&b2uframe->list);2803rtw_free_xmitframe(xmitpriv, b2uframe);2804}2805}2806#endif2807}28082809static void recv_fwd_pkt_hdl(_adapter *adapter, _pkt *pkt2810, u8 act, struct xmit_frame *fwd_frame, _list *b2u_list)2811{2812struct xmit_priv *xmitpriv = &adapter->xmitpriv;2813_pkt *fwd_pkt = pkt;28142815if (act & RTW_RX_MSDU_ACT_INDICATE) {2816fwd_pkt = rtw_os_pkt_copy(pkt);2817if (!fwd_pkt) {2818#ifdef DBG_TX_DROP_FRAME2819RTW_INFO("DBG_TX_DROP_FRAME %s rtw_os_pkt_copy fail\n", __func__);2820#endif2821recv_free_fwd_resource(adapter, fwd_frame, b2u_list);2822goto exit;2823}2824}28252826#if CONFIG_RTW_MESH_DATA_BMC_TO_UC2827if (!rtw_is_list_empty(b2u_list)) {2828_list *list = get_next(b2u_list);2829struct xmit_frame *b2uframe;28302831while (rtw_end_of_queue_search(b2u_list, list) == _FALSE) {2832b2uframe = LIST_CONTAINOR(list, struct xmit_frame, list);2833list = get_next(list);2834rtw_list_delete(&b2uframe->list);28352836if (!fwd_frame && rtw_is_list_empty(b2u_list)) /* the last fwd_pkt */2837b2uframe->pkt = fwd_pkt;2838else2839b2uframe->pkt = rtw_os_pkt_copy(fwd_pkt);2840if (!b2uframe->pkt) {2841rtw_free_xmitframe(xmitpriv, b2uframe);2842continue;2843}28442845rtw_xmit_posthandle(adapter, b2uframe, b2uframe->pkt);2846}2847}2848#endif28492850if (fwd_frame) {2851fwd_frame->pkt = fwd_pkt;2852if (rtw_xmit_posthandle(adapter, fwd_frame, fwd_pkt) < 0) {2853#ifdef DBG_TX_DROP_FRAME2854RTW_INFO("DBG_TX_DROP_FRAME %s rtw_xmit_posthandle fail\n", __func__);2855#endif2856xmitpriv->tx_drop++;2857}2858}28592860exit:2861return;2862}2863#endif /* CONFIG_RTW_MESH */28642865int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe)2866{2867struct rx_pkt_attrib *rattrib = &prframe->u.hdr.attrib;2868int a_len, padding_len;2869u16 nSubframe_Length;2870u8 nr_subframes, i;2871u8 *pdata;2872_pkt *sub_pkt, *subframes[MAX_SUBFRAME_COUNT];2873struct recv_priv *precvpriv = &padapter->recvpriv;2874_queue *pfree_recv_queue = &(precvpriv->free_recv_queue);2875const u8 *da, *sa;2876int act;2877#ifdef CONFIG_RTW_MESH /* TODO: move AP mode forward & b2u logic here */2878struct xmit_frame *fwd_frame;2879_list b2u_list;2880#endif2881u8 mctrl_len = 0;2882int ret = _SUCCESS;28832884nr_subframes = 0;28852886recvframe_pull(prframe, rattrib->hdrlen);28872888if (rattrib->iv_len > 0)2889recvframe_pull(prframe, rattrib->iv_len);28902891a_len = prframe->u.hdr.len;2892pdata = prframe->u.hdr.rx_data;28932894while (a_len > ETH_HLEN) {2895/* Offset 12 denote 2 mac address */2896nSubframe_Length = RTW_GET_BE16(pdata + 12);2897if (a_len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) {2898RTW_INFO("nRemain_Length is %d and nSubframe_Length is : %d\n", a_len, nSubframe_Length);2899break;2900}29012902act = RTW_RX_MSDU_ACT_INDICATE;29032904#ifdef CONFIG_RTW_MESH2905fwd_frame = NULL;29062907if (MLME_IS_MESH(padapter)) {2908u8 *mda = pdata, *msa = pdata + ETH_ALEN;2909struct rtw_ieee80211s_hdr *mctrl = (struct rtw_ieee80211s_hdr *)(pdata + ETH_HLEN);2910int v_ret;29112912v_ret = rtw_mesh_rx_data_validate_mctrl(padapter, prframe2913, mctrl, mda, msa, &mctrl_len, &da, &sa);2914if (v_ret != _SUCCESS)2915goto move_to_next;29162917act = rtw_mesh_rx_msdu_act_check(prframe2918, mda, msa, da, sa, mctrl, &fwd_frame, &b2u_list);2919} else2920#endif2921{2922da = pdata;2923sa = pdata + ETH_ALEN;2924}29252926#ifdef CONFIG_RTW_MESH2927if (!act)2928goto move_to_next;2929#endif29302931rtw_led_rx_control(padapter, da);29322933sub_pkt = rtw_os_alloc_msdu_pkt(prframe, da, sa2934, pdata + ETH_HLEN + mctrl_len, nSubframe_Length - mctrl_len);2935if (sub_pkt == NULL) {2936if (act & RTW_RX_MSDU_ACT_INDICATE) {2937#ifdef DBG_RX_DROP_FRAME2938RTW_INFO("DBG_RX_DROP_FRAME %s rtw_os_alloc_msdu_pkt fail\n", __func__);2939#endif2940}2941#ifdef CONFIG_RTW_MESH2942if (act & RTW_RX_MSDU_ACT_FORWARD) {2943#ifdef DBG_TX_DROP_FRAME2944RTW_INFO("DBG_TX_DROP_FRAME %s rtw_os_alloc_msdu_pkt fail\n", __func__);2945#endif2946recv_free_fwd_resource(padapter, fwd_frame, &b2u_list);2947}2948#endif2949break;2950}29512952#ifdef CONFIG_RTW_MESH2953if (act & RTW_RX_MSDU_ACT_FORWARD) {2954recv_fwd_pkt_hdl(padapter, sub_pkt, act, fwd_frame, &b2u_list);2955if (!(act & RTW_RX_MSDU_ACT_INDICATE))2956goto move_to_next;2957}2958#endif29592960if (rtw_recv_indicatepkt_check(prframe, rtw_os_pkt_data(sub_pkt), rtw_os_pkt_len(sub_pkt)) == _SUCCESS)2961subframes[nr_subframes++] = sub_pkt;2962else2963rtw_os_pkt_free(sub_pkt);29642965#ifdef CONFIG_RTW_MESH2966move_to_next:2967#endif2968/* move the data point to data content */2969pdata += ETH_HLEN;2970a_len -= ETH_HLEN;29712972if (nr_subframes >= MAX_SUBFRAME_COUNT) {2973RTW_WARN("ParseSubframe(): Too many Subframes! Packets dropped!\n");2974break;2975}29762977pdata += nSubframe_Length;2978a_len -= nSubframe_Length;2979if (a_len != 0) {2980padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & (4 - 1));2981if (padding_len == 4)2982padding_len = 0;29832984if (a_len < padding_len) {2985RTW_INFO("ParseSubframe(): a_len < padding_len !\n");2986break;2987}2988pdata += padding_len;2989a_len -= padding_len;2990}2991}29922993for (i = 0; i < nr_subframes; i++) {2994sub_pkt = subframes[i];29952996/* Indicat the packets to upper layer */2997if (sub_pkt)2998rtw_os_recv_indicate_pkt(padapter, sub_pkt, prframe);2999}30003001prframe->u.hdr.len = 0;3002rtw_free_recvframe(prframe, pfree_recv_queue);/* free this recv_frame */30033004return ret;3005}30063007static int recv_process_mpdu(_adapter *padapter, union recv_frame *prframe)3008{3009_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;3010struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;3011int ret;30123013if (pattrib->amsdu) {3014ret = amsdu_to_msdu(padapter, prframe);3015if (ret != _SUCCESS) {3016#ifdef DBG_RX_DROP_FRAME3017RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" amsdu_to_msdu fail\n"3018, FUNC_ADPT_ARG(padapter));3019#endif3020rtw_free_recvframe(prframe, pfree_recv_queue);3021goto exit;3022}3023} else {3024int act = RTW_RX_MSDU_ACT_INDICATE;30253026#ifdef CONFIG_RTW_MESH /* TODO: move AP mode forward & b2u logic here */3027struct xmit_frame *fwd_frame = NULL;3028_list b2u_list;30293030if (MLME_IS_MESH(padapter) && pattrib->mesh_ctrl_present) {3031act = rtw_mesh_rx_msdu_act_check(prframe3032, pattrib->mda, pattrib->msa3033, pattrib->dst, pattrib->src3034, (struct rtw_ieee80211s_hdr *)(get_recvframe_data(prframe) + pattrib->hdrlen + pattrib->iv_len)3035, &fwd_frame, &b2u_list);3036}3037#endif30383039#ifdef CONFIG_RTW_MESH3040if (!act) {3041rtw_free_recvframe(prframe, pfree_recv_queue);3042ret = _FAIL;3043goto exit;3044}3045#endif30463047rtw_led_rx_control(padapter, pattrib->dst);30483049ret = wlanhdr_to_ethhdr(prframe);3050if (ret != _SUCCESS) {3051if (act & RTW_RX_MSDU_ACT_INDICATE) {3052#ifdef DBG_RX_DROP_FRAME3053RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" wlanhdr_to_ethhdr: drop pkt\n"3054, FUNC_ADPT_ARG(padapter));3055#endif3056}3057#ifdef CONFIG_RTW_MESH3058if (act & RTW_RX_MSDU_ACT_FORWARD) {3059#ifdef DBG_TX_DROP_FRAME3060RTW_INFO("DBG_TX_DROP_FRAME %s wlanhdr_to_ethhdr fail\n", __func__);3061#endif3062recv_free_fwd_resource(padapter, fwd_frame, &b2u_list);3063}3064#endif3065rtw_free_recvframe(prframe, pfree_recv_queue);3066goto exit;3067}30683069#ifdef CONFIG_RTW_MESH3070if (act & RTW_RX_MSDU_ACT_FORWARD) {3071recv_fwd_pkt_hdl(padapter, prframe->u.hdr.pkt, act, fwd_frame, &b2u_list);3072if (!(act & RTW_RX_MSDU_ACT_INDICATE)) {3073prframe->u.hdr.pkt = NULL;3074rtw_free_recvframe(prframe, pfree_recv_queue);3075goto exit;3076}3077}3078#endif30793080if (!RTW_CANNOT_RUN(padapter)) {3081ret = rtw_recv_indicatepkt_check(prframe3082, get_recvframe_data(prframe), get_recvframe_len(prframe));3083if (ret != _SUCCESS) {3084rtw_free_recvframe(prframe, pfree_recv_queue);3085goto exit;3086}30873088/* indicate this recv_frame */3089ret = rtw_recv_indicatepkt(padapter, prframe);3090if (ret != _SUCCESS) {3091#ifdef DBG_RX_DROP_FRAME3092RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" rtw_recv_indicatepkt fail!\n"3093, FUNC_ADPT_ARG(padapter));3094#endif3095goto exit;3096}3097} else {3098#ifdef DBG_RX_DROP_FRAME3099RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DS:%u SR:%u\n"3100, FUNC_ADPT_ARG(padapter)3101, rtw_is_drv_stopped(padapter)3102, rtw_is_surprise_removed(padapter));3103#endif3104ret = _SUCCESS; /* don't count as packet drop */3105rtw_free_recvframe(prframe, pfree_recv_queue);3106}3107}31083109exit:3110return ret;3111}31123113#if defined(CONFIG_80211N_HT) && defined(CONFIG_RECV_REORDERING_CTRL)3114static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num)3115{3116PADAPTER padapter = preorder_ctrl->padapter;3117struct recv_priv *precvpriv = &padapter->recvpriv;3118u8 wsize = preorder_ctrl->wsize_b;3119u16 wend;31203121/* Rx Reorder initialize condition. */3122if (preorder_ctrl->indicate_seq == 0xFFFF) {3123preorder_ctrl->indicate_seq = seq_num;3124#ifdef DBG_RX_SEQ3125RTW_INFO("DBG_RX_SEQ "FUNC_ADPT_FMT" tid:%u SN_INIT indicate_seq:%d, seq_num:%d\n"3126, FUNC_ADPT_ARG(padapter), preorder_ctrl->tid, preorder_ctrl->indicate_seq, seq_num);3127#endif3128}3129wend = (preorder_ctrl->indicate_seq + wsize - 1) & 0xFFF; /* % 4096; */31303131/* Drop out the packet which SeqNum is smaller than WinStart */3132if (SN_LESS(seq_num, preorder_ctrl->indicate_seq)) {3133#ifdef DBG_RX_DROP_FRAME3134RTW_INFO(FUNC_ADPT_FMT" tid:%u indicate_seq:%d > seq_num:%d\n"3135, FUNC_ADPT_ARG(padapter), preorder_ctrl->tid, preorder_ctrl->indicate_seq, seq_num);3136#endif3137return _FALSE;3138}31393140/*3141* Sliding window manipulation. Conditions includes:3142* 1. Incoming SeqNum is equal to WinStart =>Window shift 13143* 2. Incoming SeqNum is larger than the WinEnd => Window shift N3144*/3145if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq)) {3146preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF;3147#ifdef DBG_RX_SEQ3148RTW_INFO("DBG_RX_SEQ "FUNC_ADPT_FMT" tid:%u SN_EQUAL indicate_seq:%d, seq_num:%d\n"3149, FUNC_ADPT_ARG(padapter), preorder_ctrl->tid, preorder_ctrl->indicate_seq, seq_num);3150#endif31513152} else if (SN_LESS(wend, seq_num)) {3153/* boundary situation, when seq_num cross 0xFFF */3154if (seq_num >= (wsize - 1))3155preorder_ctrl->indicate_seq = seq_num + 1 - wsize;3156else3157preorder_ctrl->indicate_seq = 0xFFF - (wsize - (seq_num + 1)) + 1;31583159precvpriv->dbg_rx_ampdu_window_shift_cnt++;3160#ifdef DBG_RX_SEQ3161RTW_INFO("DBG_RX_SEQ "FUNC_ADPT_FMT" tid:%u SN_LESS(wend, seq_num) indicate_seq:%d, seq_num:%d\n"3162, FUNC_ADPT_ARG(padapter), preorder_ctrl->tid, preorder_ctrl->indicate_seq, seq_num);3163#endif3164}31653166return _TRUE;3167}31683169static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, union recv_frame *prframe)3170{3171struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;3172_queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;3173_list *phead, *plist;3174union recv_frame *pnextrframe;3175struct rx_pkt_attrib *pnextattrib;31763177/* DbgPrint("+enqueue_reorder_recvframe()\n"); */31783179/* _enter_critical_ex(&ppending_recvframe_queue->lock, &irql); */3180/* _rtw_spinlock_ex(&ppending_recvframe_queue->lock); */318131823183phead = get_list_head(ppending_recvframe_queue);3184plist = get_next(phead);31853186while (rtw_end_of_queue_search(phead, plist) == _FALSE) {3187pnextrframe = LIST_CONTAINOR(plist, union recv_frame, u);3188pnextattrib = &pnextrframe->u.hdr.attrib;31893190if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num))3191plist = get_next(plist);3192else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) {3193/* Duplicate entry is found!! Do not insert current entry. */31943195/* _exit_critical_ex(&ppending_recvframe_queue->lock, &irql); */31963197return _FALSE;3198} else3199break;32003201/* DbgPrint("enqueue_reorder_recvframe():while\n"); */32023203}320432053206/* _enter_critical_ex(&ppending_recvframe_queue->lock, &irql); */3207/* _rtw_spinlock_ex(&ppending_recvframe_queue->lock); */32083209rtw_list_delete(&(prframe->u.hdr.list));32103211rtw_list_insert_tail(&(prframe->u.hdr.list), plist);32123213/* _rtw_spinunlock_ex(&ppending_recvframe_queue->lock); */3214/* _exit_critical_ex(&ppending_recvframe_queue->lock, &irql); */321532163217return _TRUE;32183219}32203221static void recv_indicatepkts_pkt_loss_cnt(_adapter *padapter, u64 prev_seq, u64 current_seq)3222{3223struct recv_priv *precvpriv = &padapter->recvpriv;32243225if (current_seq < prev_seq) {3226precvpriv->dbg_rx_ampdu_loss_count += (4096 + current_seq - prev_seq);3227precvpriv->rx_drop += (4096 + current_seq - prev_seq);3228} else {3229precvpriv->dbg_rx_ampdu_loss_count += (current_seq - prev_seq);3230precvpriv->rx_drop += (current_seq - prev_seq);3231}3232}32333234static int recv_indicatepkts_in_order(_adapter *padapter, struct recv_reorder_ctrl *preorder_ctrl, int bforced)3235{3236/* _irqL irql; */3237_list *phead, *plist;3238union recv_frame *prframe;3239struct rx_pkt_attrib *pattrib;3240/* u8 index = 0; */3241int bPktInBuf = _FALSE;3242struct recv_priv *precvpriv = &padapter->recvpriv;3243_queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;32443245DBG_COUNTER(padapter->rx_logs.core_rx_post_indicate_in_oder);32463247/* DbgPrint("+recv_indicatepkts_in_order\n"); */32483249/* _enter_critical_ex(&ppending_recvframe_queue->lock, &irql); */3250/* _rtw_spinlock_ex(&ppending_recvframe_queue->lock); */32513252phead = get_list_head(ppending_recvframe_queue);3253plist = get_next(phead);32543255#if 03256/* Check if there is any other indication thread running. */3257if (pTS->RxIndicateState == RXTS_INDICATE_PROCESSING)3258return;3259#endif32603261/* Handling some condition for forced indicate case. */3262if (bforced == _TRUE) {3263precvpriv->dbg_rx_ampdu_forced_indicate_count++;3264if (rtw_is_list_empty(phead)) {3265/* _exit_critical_ex(&ppending_recvframe_queue->lock, &irql); */3266/* _rtw_spinunlock_ex(&ppending_recvframe_queue->lock); */3267return _TRUE;3268}32693270prframe = LIST_CONTAINOR(plist, union recv_frame, u);3271pattrib = &prframe->u.hdr.attrib;32723273#ifdef DBG_RX_SEQ3274RTW_INFO("DBG_RX_SEQ "FUNC_ADPT_FMT" tid:%u FORCE indicate_seq:%d, seq_num:%d\n"3275, FUNC_ADPT_ARG(padapter), preorder_ctrl->tid, preorder_ctrl->indicate_seq, pattrib->seq_num);3276#endif3277recv_indicatepkts_pkt_loss_cnt(padapter, preorder_ctrl->indicate_seq, pattrib->seq_num);3278preorder_ctrl->indicate_seq = pattrib->seq_num;3279}32803281/* Prepare indication list and indication. */3282/* Check if there is any packet need indicate. */3283while (!rtw_is_list_empty(phead)) {32843285prframe = LIST_CONTAINOR(plist, union recv_frame, u);3286pattrib = &prframe->u.hdr.attrib;32873288if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {32893290#if 03291/* This protect buffer from overflow. */3292if (index >= REORDER_WIN_SIZE) {3293RT_ASSERT(FALSE, ("IndicateRxReorderList(): Buffer overflow!!\n"));3294bPktInBuf = TRUE;3295break;3296}3297#endif32983299plist = get_next(plist);3300rtw_list_delete(&(prframe->u.hdr.list));33013302if (SN_EQUAL(preorder_ctrl->indicate_seq, pattrib->seq_num)) {3303preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF;3304#ifdef DBG_RX_SEQ3305RTW_INFO("DBG_RX_SEQ "FUNC_ADPT_FMT" tid:%u SN_EQUAL indicate_seq:%d, seq_num:%d\n"3306, FUNC_ADPT_ARG(padapter), preorder_ctrl->tid, preorder_ctrl->indicate_seq, pattrib->seq_num);3307#endif3308}33093310#if 03311index++;3312if (index == 1) {3313/* Cancel previous pending timer. */3314/* PlatformCancelTimer(Adapter, &pTS->RxPktPendingTimer); */3315if (bforced != _TRUE) {3316/* RTW_INFO("_cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);\n"); */3317_cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);3318}3319}3320#endif33213322/* Set this as a lock to make sure that only one thread is indicating packet. */3323/* pTS->RxIndicateState = RXTS_INDICATE_PROCESSING; */33243325/* Indicate packets */3326/* RT_ASSERT((index<=REORDER_WIN_SIZE), ("RxReorderIndicatePacket(): Rx Reorder buffer full!!\n")); */332733283329/* indicate this recv_frame */3330/* DbgPrint("recv_indicatepkts_in_order, indicate_seq=%d, seq_num=%d\n", precvpriv->indicate_seq, pattrib->seq_num); */3331if (recv_process_mpdu(padapter, prframe) != _SUCCESS)3332precvpriv->dbg_rx_drop_count++;33333334/* Update local variables. */3335bPktInBuf = _FALSE;33363337} else {3338bPktInBuf = _TRUE;3339break;3340}33413342/* DbgPrint("recv_indicatepkts_in_order():while\n"); */33433344}33453346/* _rtw_spinunlock_ex(&ppending_recvframe_queue->lock); */3347/* _exit_critical_ex(&ppending_recvframe_queue->lock, &irql); */33483349#if 03350/* Release the indication lock and set to new indication step. */3351if (bPktInBuf) {3352/* Set new pending timer. */3353/* pTS->RxIndicateState = RXTS_INDICATE_REORDER; */3354/* PlatformSetTimer(Adapter, &pTS->RxPktPendingTimer, pHTInfo->RxReorderPendingTime); */33553356_set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);3357} else {3358/* pTS->RxIndicateState = RXTS_INDICATE_IDLE; */3359}3360#endif3361/* _exit_critical_ex(&ppending_recvframe_queue->lock, &irql); */33623363/* return _TRUE; */3364return bPktInBuf;33653366}33673368static int recv_indicatepkt_reorder(_adapter *padapter, union recv_frame *prframe)3369{3370_irqL irql;3371struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;3372struct recv_reorder_ctrl *preorder_ctrl = prframe->u.hdr.preorder_ctrl;3373_queue *ppending_recvframe_queue = preorder_ctrl ? &preorder_ctrl->pending_recvframe_queue : NULL;3374struct recv_priv *precvpriv = &padapter->recvpriv;33753376if (!pattrib->qos || !preorder_ctrl || preorder_ctrl->enable == _FALSE)3377goto _success_exit;337833793380DBG_COUNTER(padapter->rx_logs.core_rx_post_indicate_reoder);33813382_enter_critical_bh(&ppending_recvframe_queue->lock, &irql);338333843385if(rtw_test_and_clear_bit(RTW_RECV_ACK_OR_TIMEOUT, &preorder_ctrl->rec_abba_rsp_ack))3386preorder_ctrl->indicate_seq = 0xFFFF;3387#ifdef DBG_RX_SEQ3388RTW_INFO("DBG_RX_SEQ %s:preorder_ctrl->rec_abba_rsp_ack = %u,indicate_seq = %d\n"3389, __func__3390, preorder_ctrl->rec_abba_rsp_ack3391, preorder_ctrl->indicate_seq);3392#endif33933394/* s2. check if winstart_b(indicate_seq) needs to been updated */3395if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) {3396precvpriv->dbg_rx_ampdu_drop_count++;3397/* pHTInfo->RxReorderDropCounter++; */3398/* ReturnRFDList(Adapter, pRfd); */3399/* _exit_critical_ex(&ppending_recvframe_queue->lock, &irql); */3400/* return _FAIL; */34013402#ifdef DBG_RX_DROP_FRAME3403RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" check_indicate_seq fail\n"3404, FUNC_ADPT_ARG(padapter));3405#endif3406#if 03407rtw_recv_indicatepkt(padapter, prframe);34083409_exit_critical_bh(&ppending_recvframe_queue->lock, &irql);34103411goto _success_exit;3412#else3413goto _err_exit;3414#endif3415}341634173418/* s3. Insert all packet into Reorder Queue to maintain its ordering. */3419if (!enqueue_reorder_recvframe(preorder_ctrl, prframe)) {3420/* DbgPrint("recv_indicatepkt_reorder, enqueue_reorder_recvframe fail!\n"); */3421/* _exit_critical_ex(&ppending_recvframe_queue->lock, &irql); */3422/* return _FAIL; */3423#ifdef DBG_RX_DROP_FRAME3424RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" enqueue_reorder_recvframe fail\n"3425, FUNC_ADPT_ARG(padapter));3426#endif3427goto _err_exit;3428}342934303431/* s4. */3432/* Indication process. */3433/* After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets */3434/* with the SeqNum smaller than latest WinStart and buffer other packets. */3435/* */3436/* For Rx Reorder condition: */3437/* 1. All packets with SeqNum smaller than WinStart => Indicate */3438/* 2. All packets with SeqNum larger than or equal to WinStart => Buffer it. */3439/* */34403441/* recv_indicatepkts_in_order(padapter, preorder_ctrl, _TRUE); */3442if (recv_indicatepkts_in_order(padapter, preorder_ctrl, _FALSE) == _TRUE) {3443if (!preorder_ctrl->bReorderWaiting) {3444preorder_ctrl->bReorderWaiting = _TRUE;3445_set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);3446}3447_exit_critical_bh(&ppending_recvframe_queue->lock, &irql);3448} else {3449preorder_ctrl->bReorderWaiting = _FALSE;3450_exit_critical_bh(&ppending_recvframe_queue->lock, &irql);3451_cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);3452}34533454return RTW_RX_HANDLED;34553456_success_exit:34573458return _SUCCESS;34593460_err_exit:34613462_exit_critical_bh(&ppending_recvframe_queue->lock, &irql);34633464return _FAIL;3465}346634673468void rtw_reordering_ctrl_timeout_handler(void *pcontext)3469{3470_irqL irql;3471struct recv_reorder_ctrl *preorder_ctrl = (struct recv_reorder_ctrl *)pcontext;3472_adapter *padapter = NULL;3473_queue *ppending_recvframe_queue = NULL;347434753476if (preorder_ctrl == NULL)3477return;34783479padapter = preorder_ctrl->padapter;3480if (RTW_CANNOT_RUN(padapter))3481return;34823483ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;34843485/* RTW_INFO("+rtw_reordering_ctrl_timeout_handler()=>\n"); */34863487_enter_critical_bh(&ppending_recvframe_queue->lock, &irql);34883489preorder_ctrl->bReorderWaiting = _FALSE;34903491if (recv_indicatepkts_in_order(padapter, preorder_ctrl, _TRUE) == _TRUE)3492_set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);34933494_exit_critical_bh(&ppending_recvframe_queue->lock, &irql);34953496}3497#endif /* defined(CONFIG_80211N_HT) && defined(CONFIG_RECV_REORDERING_CTRL) */34983499static void recv_set_iseq_before_mpdu_process(union recv_frame *rframe, u16 seq_num, const char *caller)3500{3501#if defined(CONFIG_80211N_HT) && defined(CONFIG_RECV_REORDERING_CTRL)3502struct recv_reorder_ctrl *reorder_ctrl = rframe->u.hdr.preorder_ctrl;35033504if (reorder_ctrl) {3505reorder_ctrl->indicate_seq = seq_num;3506#ifdef DBG_RX_SEQ3507RTW_INFO("DBG_RX_SEQ %s("ADPT_FMT")-B tid:%u indicate_seq:%d, seq_num:%d\n"3508, caller, ADPT_ARG(reorder_ctrl->padapter)3509, reorder_ctrl->tid, reorder_ctrl->indicate_seq, seq_num);3510#endif3511}3512#endif3513}35143515static void recv_set_iseq_after_mpdu_process(union recv_frame *rframe, u16 seq_num, const char *caller)3516{3517#if defined(CONFIG_80211N_HT) && defined(CONFIG_RECV_REORDERING_CTRL)3518struct recv_reorder_ctrl *reorder_ctrl = rframe->u.hdr.preorder_ctrl;35193520if (reorder_ctrl) {3521reorder_ctrl->indicate_seq = (reorder_ctrl->indicate_seq + 1) % 4096;3522#ifdef DBG_RX_SEQ3523RTW_INFO("DBG_RX_SEQ %s("ADPT_FMT")-A tid:%u indicate_seq:%d, seq_num:%d\n"3524, caller, ADPT_ARG(reorder_ctrl->padapter)3525, reorder_ctrl->tid, reorder_ctrl->indicate_seq, seq_num);3526#endif3527}3528#endif3529}35303531#ifdef CONFIG_MP_INCLUDED3532int validate_mp_recv_frame(_adapter *adapter, union recv_frame *precv_frame)3533{3534int ret = _SUCCESS;3535u8 *ptr = precv_frame->u.hdr.rx_data;3536u8 type, subtype;3537struct mp_priv *pmppriv = &adapter->mppriv;3538struct mp_tx *pmptx;3539unsigned char *sa , *da, *bs;3540struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;3541u32 i = 0;3542u8 rtk_prefix[]={0x52, 0x65, 0x61, 0x6C, 0x4C, 0x6F, 0x76, 0x65, 0x54, 0x65, 0x6B};3543u8 *prx_data;3544pmptx = &pmppriv->tx;354535463547if (pmppriv->mplink_brx == _FALSE) {35483549u8 bDumpRxPkt = 0;3550type = GetFrameType(ptr);3551subtype = get_frame_sub_type(ptr); /* bit(7)~bit(2) */35523553RTW_INFO("hdr len = %d iv_len=%d \n", pattrib->hdrlen , pattrib->iv_len);3554prx_data = ptr + pattrib->hdrlen + pattrib->iv_len;35553556for (i = 0; i < precv_frame->u.hdr.len; i++) {3557if (precv_frame->u.hdr.len < (11 + i))3558break;35593560if (_rtw_memcmp(prx_data + i, (void *)&rtk_prefix, 11) == _FALSE) {3561bDumpRxPkt = 0;3562RTW_DBG("prx_data = %02X != rtk_prefix[%d] = %02X \n", *(prx_data + i), i , rtk_prefix[i]);3563} else {3564bDumpRxPkt = 1;3565RTW_DBG("prx_data = %02X = rtk_prefix[%d] = %02X \n", *(prx_data + i), i , rtk_prefix[i]);3566break;3567}3568}35693570if (bDumpRxPkt == 1) { /* dump all rx packets */3571int i;3572RTW_INFO("############ type:0x%02x subtype:0x%02x #################\n", type, subtype);35733574for (i = 0; i < precv_frame->u.hdr.len; i = i + 8)3575RTW_INFO("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr + i),3576*(ptr + i + 1), *(ptr + i + 2) , *(ptr + i + 3) , *(ptr + i + 4), *(ptr + i + 5), *(ptr + i + 6), *(ptr + i + 7));3577RTW_INFO("#############################\n");3578_rtw_memset(pmppriv->mplink_buf, '\0' , sizeof(pmppriv->mplink_buf));3579_rtw_memcpy(pmppriv->mplink_buf, ptr, precv_frame->u.hdr.len);3580pmppriv->mplink_rx_len = precv_frame->u.hdr.len;3581pmppriv->mplink_brx =_TRUE;3582}3583}3584if (pmppriv->bloopback) {3585if (_rtw_memcmp(ptr + 24, pmptx->buf + 24, precv_frame->u.hdr.len - 24) == _FALSE) {3586RTW_INFO("Compare payload content Fail !!!\n");3587ret = _FAIL;3588}3589}3590if (pmppriv->bSetRxBssid == _TRUE) {35913592sa = get_addr2_ptr(ptr);3593da = GetAddr1Ptr(ptr);3594bs = GetAddr3Ptr(ptr);3595type = GetFrameType(ptr);3596subtype = get_frame_sub_type(ptr); /* bit(7)~bit(2) */35973598if (_rtw_memcmp(bs, adapter->mppriv.network_macaddr, ETH_ALEN) == _FALSE)3599ret = _FAIL;36003601RTW_DBG("############ type:0x%02x subtype:0x%02x #################\n", type, subtype);3602RTW_DBG("A2 sa %02X:%02X:%02X:%02X:%02X:%02X \n", *(sa) , *(sa + 1), *(sa+ 2), *(sa + 3), *(sa + 4), *(sa + 5));3603RTW_DBG("A1 da %02X:%02X:%02X:%02X:%02X:%02X \n", *(da) , *(da + 1), *(da+ 2), *(da + 3), *(da + 4), *(da + 5));3604RTW_DBG("A3 bs %02X:%02X:%02X:%02X:%02X:%02X \n --------------------------\n", *(bs) , *(bs + 1), *(bs+ 2), *(bs + 3), *(bs + 4), *(bs + 5));3605}36063607if (!adapter->mppriv.bmac_filter)3608return ret;36093610if (_rtw_memcmp(get_addr2_ptr(ptr), adapter->mppriv.mac_filter, ETH_ALEN) == _FALSE)3611ret = _FAIL;36123613return ret;3614}36153616static sint MPwlanhdr_to_ethhdr(union recv_frame *precvframe)3617{3618sint rmv_len;3619u16 eth_type, len;3620u8 bsnaphdr;3621u8 *psnap_type;3622u8 mcastheadermac[] = {0x01, 0x00, 0x5e};36233624struct ieee80211_snap_hdr *psnap;36253626sint ret = _SUCCESS;3627_adapter *adapter = precvframe->u.hdr.adapter;36283629u8 *ptr = get_recvframe_data(precvframe) ; /* point to frame_ctrl field */3630struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;363136323633if (pattrib->encrypt)3634recvframe_pull_tail(precvframe, pattrib->icv_len);36353636psnap = (struct ieee80211_snap_hdr *)(ptr + pattrib->hdrlen + pattrib->iv_len);3637psnap_type = ptr + pattrib->hdrlen + pattrib->iv_len + SNAP_SIZE;3638/* convert hdr + possible LLC headers into Ethernet header */3639/* eth_type = (psnap_type[0] << 8) | psnap_type[1]; */3640if ((_rtw_memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) &&3641(_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) == _FALSE) &&3642(_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_AARP, 2) == _FALSE)) ||3643/* eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || */3644_rtw_memcmp(psnap, rtw_bridge_tunnel_header, SNAP_SIZE)) {3645/* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */3646bsnaphdr = _TRUE;3647} else {3648/* Leave Ethernet header part of hdr and full payload */3649bsnaphdr = _FALSE;3650}36513652rmv_len = pattrib->hdrlen + pattrib->iv_len + (bsnaphdr ? SNAP_SIZE : 0);3653len = precvframe->u.hdr.len - rmv_len;365436553656_rtw_memcpy(ð_type, ptr + rmv_len, 2);3657eth_type = ntohs((unsigned short)eth_type); /* pattrib->ether_type */3658pattrib->eth_type = eth_type;36593660{3661ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0)));3662}36633664_rtw_memcpy(ptr, pattrib->dst, ETH_ALEN);3665_rtw_memcpy(ptr + ETH_ALEN, pattrib->src, ETH_ALEN);36663667if (!bsnaphdr) {3668len = htons(len);3669_rtw_memcpy(ptr + 12, &len, 2);3670}367136723673len = htons(pattrib->seq_num);3674/* RTW_INFO("wlan seq = %d ,seq_num =%x\n",len,pattrib->seq_num); */3675_rtw_memcpy(ptr + 12, &len, 2);3676if (adapter->mppriv.bRTWSmbCfg == _TRUE) {3677/* if(_rtw_memcmp(mcastheadermac, pattrib->dst, 3) == _TRUE) */ /* SimpleConfig Dest. */3678/* _rtw_memcpy(ptr+ETH_ALEN, pattrib->bssid, ETH_ALEN); */36793680if (_rtw_memcmp(mcastheadermac, pattrib->bssid, 3) == _TRUE) /* SimpleConfig Dest. */3681_rtw_memcpy(ptr, pattrib->bssid, ETH_ALEN);36823683}368436853686return ret;36873688}368936903691int mp_recv_frame(_adapter *padapter, union recv_frame *rframe)3692{3693int ret = _SUCCESS;3694struct rx_pkt_attrib *pattrib = &rframe->u.hdr.attrib;3695_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;3696#ifdef CONFIG_MP_INCLUDED3697struct mlme_priv *pmlmepriv = &padapter->mlmepriv;3698struct mp_priv *pmppriv = &padapter->mppriv;3699#endif /* CONFIG_MP_INCLUDED */3700u8 type;3701u8 *ptr = rframe->u.hdr.rx_data;3702u8 *psa, *pda, *pbssid;3703struct sta_info *psta = NULL;3704DBG_COUNTER(padapter->rx_logs.core_rx_pre);37053706if ((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)) { /* &&(padapter->mppriv.check_mp_pkt == 0)) */3707if (pattrib->crc_err == 1)3708padapter->mppriv.rx_crcerrpktcount++;3709else {3710if (_SUCCESS == validate_mp_recv_frame(padapter, rframe))3711padapter->mppriv.rx_pktcount++;3712else3713padapter->mppriv.rx_pktcount_filter_out++;3714}37153716if (pmppriv->rx_bindicatePkt == _FALSE) {3717ret = _FAIL;3718rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */3719goto exit;3720} else {3721type = GetFrameType(ptr);3722pattrib->to_fr_ds = get_tofr_ds(ptr);3723pattrib->frag_num = GetFragNum(ptr);3724pattrib->seq_num = GetSequence(ptr);3725pattrib->pw_save = GetPwrMgt(ptr);3726pattrib->mfrag = GetMFrag(ptr);3727pattrib->mdata = GetMData(ptr);3728pattrib->privacy = GetPrivacy(ptr);3729pattrib->order = GetOrder(ptr);37303731if (type == WIFI_DATA_TYPE) {3732pda = get_da(ptr);3733psa = get_sa(ptr);3734pbssid = get_hdr_bssid(ptr);37353736_rtw_memcpy(pattrib->dst, pda, ETH_ALEN);3737_rtw_memcpy(pattrib->src, psa, ETH_ALEN);3738_rtw_memcpy(pattrib->bssid, pbssid, ETH_ALEN);37393740switch (pattrib->to_fr_ds) {3741case 0:3742_rtw_memcpy(pattrib->ra, pda, ETH_ALEN);3743_rtw_memcpy(pattrib->ta, psa, ETH_ALEN);3744ret = sta2sta_data_frame(padapter, rframe, &psta);3745break;37463747case 1:37483749_rtw_memcpy(pattrib->ra, pda, ETH_ALEN);3750_rtw_memcpy(pattrib->ta, pbssid, ETH_ALEN);3751ret = ap2sta_data_frame(padapter, rframe, &psta);37523753break;37543755case 2:3756_rtw_memcpy(pattrib->ra, pbssid, ETH_ALEN);3757_rtw_memcpy(pattrib->ta, psa, ETH_ALEN);3758ret = sta2ap_data_frame(padapter, rframe, &psta);3759break;37603761case 3:3762_rtw_memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);3763_rtw_memcpy(pattrib->ta, get_addr2_ptr(ptr), ETH_ALEN);3764ret = _FAIL;3765break;37663767default:3768ret = _FAIL;3769break;3770}37713772ret = MPwlanhdr_to_ethhdr(rframe);37733774if (ret != _SUCCESS) {3775#ifdef DBG_RX_DROP_FRAME3776RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" wlanhdr_to_ethhdr: drop pkt\n"3777, FUNC_ADPT_ARG(padapter));3778#endif3779rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */3780ret = _FAIL;3781goto exit;3782}3783if (!RTW_CANNOT_RUN(padapter)) {3784/* indicate this recv_frame */3785ret = rtw_recv_indicatepkt(padapter, rframe);3786if (ret != _SUCCESS) {3787#ifdef DBG_RX_DROP_FRAME3788RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" rtw_recv_indicatepkt fail!\n"3789, FUNC_ADPT_ARG(padapter));3790#endif3791rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */3792ret = _FAIL;37933794goto exit;3795}3796} else {3797#ifdef DBG_RX_DROP_FRAME3798RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" bDriverStopped(%s) OR bSurpriseRemoved(%s)\n"3799, FUNC_ADPT_ARG(padapter)3800, rtw_is_drv_stopped(padapter) ? "True" : "False"3801, rtw_is_surprise_removed(padapter) ? "True" : "False");3802#endif3803ret = _FAIL;3804rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */3805goto exit;3806}38073808}3809}38103811}38123813rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */3814ret = _FAIL;38153816exit:3817return ret;38183819}3820#endif38213822static sint fill_radiotap_hdr(_adapter *padapter, union recv_frame *precvframe, u8 *buf)3823{3824#define CHAN2FREQ(a) ((a < 14) ? (2407+5*a) : (5000+5*a))38253826#if 03827#define RTW_RX_RADIOTAP_PRESENT (\3828(1 << IEEE80211_RADIOTAP_TSFT) | \3829(1 << IEEE80211_RADIOTAP_FLAGS) | \3830(1 << IEEE80211_RADIOTAP_RATE) | \3831(1 << IEEE80211_RADIOTAP_CHANNEL) | \3832(0 << IEEE80211_RADIOTAP_FHSS) | \3833(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \3834(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \3835(0 << IEEE80211_RADIOTAP_LOCK_QUALITY) | \3836(0 << IEEE80211_RADIOTAP_TX_ATTENUATION) | \3837(0 << IEEE80211_RADIOTAP_DB_TX_ATTENUATION) | \3838(0 << IEEE80211_RADIOTAP_DBM_TX_POWER) | \3839(1 << IEEE80211_RADIOTAP_ANTENNA) | \3840(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \3841(0 << IEEE80211_RADIOTAP_DB_ANTNOISE) | \3842(0 << IEEE80211_RADIOTAP_RX_FLAGS) | \3843(0 << IEEE80211_RADIOTAP_TX_FLAGS) | \3844(0 << IEEE80211_RADIOTAP_RTS_RETRIES) | \3845(0 << IEEE80211_RADIOTAP_DATA_RETRIES) | \3846(0 << IEEE80211_RADIOTAP_MCS) | \3847(0 << IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE)| \3848(0 << IEEE80211_RADIOTAP_VENDOR_NAMESPACE) | \3849(0 << IEEE80211_RADIOTAP_EXT) | \38500)38513852/* (0 << IEEE80211_RADIOTAP_AMPDU_STATUS) | \ */3853/* (0 << IEEE80211_RADIOTAP_VHT) | \ */3854#endif38553856#ifndef IEEE80211_RADIOTAP_RX_FLAGS3857#define IEEE80211_RADIOTAP_RX_FLAGS 143858#endif38593860#ifndef IEEE80211_RADIOTAP_MCS3861#define IEEE80211_RADIOTAP_MCS 193862#endif3863#ifndef IEEE80211_RADIOTAP_VHT3864#define IEEE80211_RADIOTAP_VHT 213865#endif38663867#ifndef IEEE80211_RADIOTAP_F_BADFCS3868#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* bad FCS */3869#endif38703871sint ret = _SUCCESS;3872struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;38733874HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);38753876u16 tmp_16bit = 0;38773878u8 data_rate[] = {38792, 4, 11, 22, /* CCK */388012, 18, 24, 36, 48, 72, 96, 108, /* OFDM */38810, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* HT MCS index */388216, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,38830, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* VHT Nss 1 */38840, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* VHT Nss 2 */38850, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* VHT Nss 3 */38860, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* VHT Nss 4 */3887};38883889_pkt *pskb = NULL;38903891struct ieee80211_radiotap_header *rtap_hdr = NULL;3892u8 *ptr = NULL;38933894u8 hdr_buf[64] = {0};3895u16 rt_len = 8;38963897/* create header */3898rtap_hdr = (struct ieee80211_radiotap_header *)&hdr_buf[0];3899rtap_hdr->it_version = PKTHDR_RADIOTAP_VERSION;39003901/* tsft */3902if (pattrib->tsfl) {3903u64 tmp_64bit;39043905rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_TSFT);3906tmp_64bit = cpu_to_le64(pattrib->tsfl);3907memcpy(&hdr_buf[rt_len], &tmp_64bit, 8);3908rt_len += 8;3909}39103911/* flags */3912rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_FLAGS);3913if (0)3914hdr_buf[rt_len] |= IEEE80211_RADIOTAP_F_CFP;39153916if (0)3917hdr_buf[rt_len] |= IEEE80211_RADIOTAP_F_SHORTPRE;39183919if ((pattrib->encrypt == 1) || (pattrib->encrypt == 5))3920hdr_buf[rt_len] |= IEEE80211_RADIOTAP_F_WEP;39213922if (pattrib->mfrag)3923hdr_buf[rt_len] |= IEEE80211_RADIOTAP_F_FRAG;39243925/* always append FCS */3926hdr_buf[rt_len] |= IEEE80211_RADIOTAP_F_FCS;39273928if (0)3929hdr_buf[rt_len] |= IEEE80211_RADIOTAP_F_DATAPAD;39303931if (pattrib->crc_err)3932hdr_buf[rt_len] |= IEEE80211_RADIOTAP_F_BADFCS;39333934if (pattrib->sgi) {3935/* Currently unspecified but used */3936hdr_buf[rt_len] |= 0x80;3937}3938rt_len += 1;39393940/* rate */3941if (pattrib->data_rate <= DESC_RATE54M) {3942rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_RATE);3943if (pattrib->data_rate <= DESC_RATE11M) {3944/* CCK */3945hdr_buf[rt_len] = data_rate[pattrib->data_rate];3946} else {3947/* OFDM */3948hdr_buf[rt_len] = data_rate[pattrib->data_rate];3949}3950}3951rt_len += 1; /* force padding 1 byte for aligned */39523953/* channel */3954tmp_16bit = 0;3955rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_CHANNEL);3956tmp_16bit = CHAN2FREQ(rtw_get_oper_ch(padapter));3957/*tmp_16bit = CHAN2FREQ(pHalData->current_channel);*/3958memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);3959rt_len += 2;39603961/* channel flags */3962// tmp_16bit = 0;3963// if (pHalData->current_band_type == BAND_ON_2_4G)3964// tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_2GHZ);3965// else /*BAND_ON_5G*/3966// tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_5GHZ);3967// NOTE: tmp_16bit currently contains channel freq; we overwrite the value3968// to reflect channel flags.3969if (pHalData->current_band_type == BAND_ON_2_4G){3970tmp_16bit = cpu_to_le16(IEEE80211_CHAN_2GHZ);3971}3972else if (pHalData->current_band_type == BAND_ON_5G)3973tmp_16bit = cpu_to_le16(IEEE80211_CHAN_5GHZ);3974else { // BAND_ON_BOTH; decide based on frequency3975if (tmp_16bit >= 5000) {3976tmp_16bit = cpu_to_le16(IEEE80211_CHAN_5GHZ);3977} else {3978tmp_16bit = cpu_to_le16(IEEE80211_CHAN_2GHZ);3979}3980}39813982if (pattrib->data_rate <= DESC_RATE54M) {3983if (pattrib->data_rate <= DESC_RATE11M) {3984/* CCK */3985tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_CCK);3986} else {3987/* OFDM */3988tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_OFDM);3989}3990} else3991tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_DYN);3992memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);3993rt_len += 2;39943995/* dBm Antenna Signal */3996rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);3997hdr_buf[rt_len] = pattrib->phy_info.recv_signal_power;3998rt_len += 1;39994000#if 04001/* dBm Antenna Noise */4002rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE);4003hdr_buf[rt_len] = 0;4004rt_len += 1;40054006/* Signal Quality */4007rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_LOCK_QUALITY);4008hdr_buf[rt_len] = pattrib->phy_info.signal_quality;4009rt_len += 1;4010#endif40114012/* Antenna */4013rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_ANTENNA);4014hdr_buf[rt_len] = 0; /* pHalData->rf_type; */4015rt_len += 1;40164017/* RX flags */4018rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_RX_FLAGS);4019#if 04020tmp_16bit = cpu_to_le16(0);4021memcpy(ptr, &tmp_16bit, 1);4022#endif4023rt_len += 2;40244025/* MCS information */4026if (pattrib->data_rate >= DESC_RATEMCS0 && pattrib->data_rate <= DESC_RATEMCS31) {4027rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_MCS);4028/* known, flag */4029hdr_buf[rt_len] |= BIT1; /* MCS index known */40304031/* bandwidth */4032hdr_buf[rt_len] |= BIT0;4033hdr_buf[rt_len + 1] |= (pattrib->bw & 0x03);40344035/* guard interval */4036hdr_buf[rt_len] |= BIT2;4037hdr_buf[rt_len + 1] |= (pattrib->sgi & 0x01) << 2;40384039/* STBC */4040hdr_buf[rt_len] |= BIT5;4041hdr_buf[rt_len + 1] |= (pattrib->stbc & 0x03) << 5;40424043rt_len += 2;40444045/* MCS rate index */4046hdr_buf[rt_len] = data_rate[pattrib->data_rate];4047rt_len += 1;4048}40494050/* VHT */4051if (pattrib->data_rate >= DESC_RATEVHTSS1MCS0 && pattrib->data_rate <= DESC_RATEVHTSS4MCS9) {4052rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_VHT);40534054/* known 16 bit, flag 8 bit */4055tmp_16bit = 0;40564057/* Bandwidth */4058tmp_16bit |= BIT6;40594060/* Group ID */4061tmp_16bit |= BIT7;40624063/* Partial AID */4064tmp_16bit |= BIT8;40654066/* STBC */4067tmp_16bit |= BIT0;4068hdr_buf[rt_len + 2] |= (pattrib->stbc & 0x01);40694070/* Guard interval */4071tmp_16bit |= BIT2;4072hdr_buf[rt_len + 2] |= (pattrib->sgi & 0x01) << 2;40734074/* LDPC extra OFDM symbol */4075tmp_16bit |= BIT4;4076hdr_buf[rt_len + 2] |= (pattrib->ldpc & 0x01) << 4;40774078memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);4079rt_len += 3;40804081/* bandwidth */4082if (pattrib->bw == 0)4083hdr_buf[rt_len] |= 0;4084else if (pattrib->bw == 1)4085hdr_buf[rt_len] |= 1;4086else if (pattrib->bw == 2)4087hdr_buf[rt_len] |= 4;4088else if (pattrib->bw == 3)4089hdr_buf[rt_len] |= 11;4090rt_len += 1;40914092/* mcs_nss */4093if (pattrib->data_rate >= DESC_RATEVHTSS1MCS0 && pattrib->data_rate <= DESC_RATEVHTSS1MCS9) {4094hdr_buf[rt_len] |= 1;4095hdr_buf[rt_len] |= data_rate[pattrib->data_rate] << 4;4096} else if (pattrib->data_rate >= DESC_RATEVHTSS2MCS0 && pattrib->data_rate <= DESC_RATEVHTSS2MCS9) {4097hdr_buf[rt_len + 1] |= 2;4098hdr_buf[rt_len + 1] |= data_rate[pattrib->data_rate] << 4;4099} else if (pattrib->data_rate >= DESC_RATEVHTSS3MCS0 && pattrib->data_rate <= DESC_RATEVHTSS3MCS9) {4100hdr_buf[rt_len + 2] |= 3;4101hdr_buf[rt_len + 2] |= data_rate[pattrib->data_rate] << 4;4102} else if (pattrib->data_rate >= DESC_RATEVHTSS4MCS0 && pattrib->data_rate <= DESC_RATEVHTSS4MCS9) {4103hdr_buf[rt_len + 3] |= 4;4104hdr_buf[rt_len + 3] |= data_rate[pattrib->data_rate] << 4;4105}4106rt_len += 4;41074108/* coding */4109hdr_buf[rt_len] = 0;4110rt_len += 1;41114112/* group_id */4113hdr_buf[rt_len] = 0;4114rt_len += 1;41154116/* partial_aid */4117tmp_16bit = 0;4118memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);4119rt_len += 2;4120}41214122/* push to skb */4123pskb = (_pkt *)buf;4124if (skb_headroom(pskb) < rt_len) {4125RTW_INFO("%s:%d %s headroom is too small.\n", __FILE__, __LINE__, __func__);4126ret = _FAIL;4127return ret;4128}41294130ptr = skb_push(pskb, rt_len);4131if (ptr) {4132rtap_hdr->it_len = cpu_to_le16(rt_len);4133rtap_hdr->it_present = cpu_to_le32(rtap_hdr->it_present);4134memcpy(ptr, rtap_hdr, rt_len);4135} else4136ret = _FAIL;41374138return ret;41394140}4141#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24))4142int recv_frame_monitor(_adapter *padapter, union recv_frame *rframe)4143{4144int ret = _SUCCESS;4145_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;4146_pkt *pskb = NULL;41474148/* read skb information from recv frame */4149pskb = rframe->u.hdr.pkt;4150pskb->len = rframe->u.hdr.len;4151pskb->data = rframe->u.hdr.rx_data;4152skb_set_tail_pointer(pskb, rframe->u.hdr.len);41534154#ifndef CONFIG_CUSTOMER_ALIBABA_GENERAL4155/* fill radiotap header */4156if (fill_radiotap_hdr(padapter, rframe, (u8 *)pskb) == _FAIL) {4157ret = _FAIL;4158rtw_free_recvframe(rframe, pfree_recv_queue); /* free this recv_frame */4159goto exit;4160}4161#endif4162/* write skb information to recv frame */4163skb_reset_mac_header(pskb);4164rframe->u.hdr.len = pskb->len;4165rframe->u.hdr.rx_data = pskb->data;4166rframe->u.hdr.rx_head = pskb->head;4167rframe->u.hdr.rx_tail = skb_tail_pointer(pskb);4168rframe->u.hdr.rx_end = skb_end_pointer(pskb);41694170if (!RTW_CANNOT_RUN(padapter)) {4171/* indicate this recv_frame */4172ret = rtw_recv_monitor(padapter, rframe);4173if (ret != _SUCCESS) {4174ret = _FAIL;4175rtw_free_recvframe(rframe, pfree_recv_queue); /* free this recv_frame */4176goto exit;4177}4178} else {4179ret = _FAIL;4180rtw_free_recvframe(rframe, pfree_recv_queue); /* free this recv_frame */4181goto exit;4182}41834184exit:4185return ret;4186}4187#endif4188int recv_func_prehandle(_adapter *padapter, union recv_frame *rframe)4189{4190int ret = _SUCCESS;4191#ifdef DBG_RX_COUNTER_DUMP4192struct rx_pkt_attrib *pattrib = &rframe->u.hdr.attrib;4193#endif4194_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;41954196#ifdef DBG_RX_COUNTER_DUMP4197if (padapter->dump_rx_cnt_mode & DUMP_DRV_RX_COUNTER) {4198if (pattrib->crc_err == 1)4199padapter->drv_rx_cnt_crcerror++;4200else4201padapter->drv_rx_cnt_ok++;4202}4203#endif42044205#ifdef CONFIG_MP_INCLUDED4206if (padapter->registrypriv.mp_mode == 1 || padapter->mppriv.bRTWSmbCfg == _TRUE) {4207mp_recv_frame(padapter, rframe);4208ret = _FAIL;4209goto exit;4210} else4211#endif4212{4213/* check the frame crtl field and decache */4214ret = validate_recv_frame(padapter, rframe);4215if (ret != _SUCCESS) {4216rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */4217goto exit;4218}4219}4220exit:4221return ret;4222}42234224/*#define DBG_RX_BMC_FRAME*/4225int recv_func_posthandle(_adapter *padapter, union recv_frame *prframe)4226{4227int ret = _SUCCESS;4228union recv_frame *orig_prframe = prframe;4229struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;4230struct recv_priv *precvpriv = &padapter->recvpriv;4231_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;4232#ifdef CONFIG_TDLS4233u8 *psnap_type, *pcategory;4234#endif /* CONFIG_TDLS */42354236DBG_COUNTER(padapter->rx_logs.core_rx_post);42374238prframe = decryptor(padapter, prframe);4239if (prframe == NULL) {4240#ifdef DBG_RX_DROP_FRAME4241RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" decryptor: drop pkt\n"4242, FUNC_ADPT_ARG(padapter));4243#endif4244ret = _FAIL;4245DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_err);4246goto _recv_data_drop;4247}42484249#ifdef DBG_RX_BMC_FRAME4250if (IS_MCAST(pattrib->ra))4251RTW_INFO("%s =>"ADPT_FMT" Rx BC/MC from "MAC_FMT"\n", __func__, ADPT_ARG(padapter), MAC_ARG(pattrib->ta));4252#endif42534254#if 04255if (is_primary_adapter(padapter)) {4256RTW_INFO("+++\n");4257{4258int i;4259u8 *ptr = get_recvframe_data(prframe);4260for (i = 0; i < 140; i = i + 8)4261RTW_INFO("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:", *(ptr + i),4262*(ptr + i + 1), *(ptr + i + 2) , *(ptr + i + 3) , *(ptr + i + 4), *(ptr + i + 5), *(ptr + i + 6), *(ptr + i + 7));42634264}4265RTW_INFO("---\n");4266}4267#endif42684269#ifdef CONFIG_TDLS4270/* check TDLS frame */4271psnap_type = get_recvframe_data(orig_prframe) + pattrib->hdrlen + pattrib->iv_len + SNAP_SIZE;4272pcategory = psnap_type + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN;42734274if ((_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_TDLS, ETH_TYPE_LEN)) &&4275((*pcategory == RTW_WLAN_CATEGORY_TDLS) || (*pcategory == RTW_WLAN_CATEGORY_P2P))) {4276ret = OnTDLS(padapter, prframe);4277if (ret == _FAIL)4278goto _exit_recv_func;4279}4280#endif /* CONFIG_TDLS */42814282prframe = recvframe_chk_defrag(padapter, prframe);4283if (prframe == NULL) {4284#ifdef DBG_RX_DROP_FRAME4285RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" recvframe_chk_defrag: drop pkt\n"4286, FUNC_ADPT_ARG(padapter));4287#endif4288DBG_COUNTER(padapter->rx_logs.core_rx_post_defrag_err);4289goto _recv_data_drop;4290}42914292prframe = portctrl(padapter, prframe);4293if (prframe == NULL) {4294#ifdef DBG_RX_DROP_FRAME4295RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" portctrl: drop pkt\n"4296, FUNC_ADPT_ARG(padapter));4297#endif4298ret = _FAIL;4299DBG_COUNTER(padapter->rx_logs.core_rx_post_portctrl_err);4300goto _recv_data_drop;4301}43024303count_rx_stats(padapter, prframe, NULL);43044305#ifdef CONFIG_WAPI_SUPPORT4306rtw_wapi_update_info(padapter, prframe);4307#endif43084309#if defined(CONFIG_80211N_HT) && defined(CONFIG_RECV_REORDERING_CTRL)4310/* including perform A-MPDU Rx Ordering Buffer Control */4311ret = recv_indicatepkt_reorder(padapter, prframe);4312if (ret == _FAIL) {4313rtw_free_recvframe(orig_prframe, pfree_recv_queue);4314goto _recv_data_drop;4315} else if (ret == RTW_RX_HANDLED) /* queued OR indicated in order */4316goto _exit_recv_func;4317#endif43184319recv_set_iseq_before_mpdu_process(prframe, pattrib->seq_num, __func__);4320ret = recv_process_mpdu(padapter, prframe);4321recv_set_iseq_after_mpdu_process(prframe, pattrib->seq_num, __func__);4322if (ret == _FAIL)4323goto _recv_data_drop;43244325_exit_recv_func:4326return ret;43274328_recv_data_drop:4329precvpriv->dbg_rx_drop_count++;4330return ret;4331}43324333int recv_func(_adapter *padapter, union recv_frame *rframe)4334{4335int ret;4336struct rx_pkt_attrib *prxattrib = &rframe->u.hdr.attrib;4337struct recv_priv *recvpriv = &padapter->recvpriv;4338struct security_priv *psecuritypriv = &padapter->securitypriv;4339struct mlme_priv *mlmepriv = &padapter->mlmepriv;4340#ifdef CONFIG_CUSTOMER_ALIBABA_GENERAL4341u8 type;4342u8 *ptr = rframe->u.hdr.rx_data;4343#endif4344if (check_fwstate(mlmepriv, WIFI_MONITOR_STATE)) {4345/* monitor mode */4346#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24))4347recv_frame_monitor(padapter, rframe);4348#endif4349ret = _SUCCESS;4350goto exit;4351} else4352{}4353#ifdef CONFIG_CUSTOMER_ALIBABA_GENERAL4354type = GetFrameType(ptr);4355if ((type == WIFI_DATA_TYPE)&& check_fwstate(mlmepriv, WIFI_STATION_STATE)) {4356struct wlan_network *cur_network = &(mlmepriv->cur_network);4357if ( _rtw_memcmp(get_addr2_ptr(ptr), cur_network->network.MacAddress, ETH_ALEN)==0) {4358recv_frame_monitor(padapter, rframe);4359ret = _SUCCESS;4360goto exit;4361}4362}4363#endif4364/* check if need to handle uc_swdec_pending_queue*/4365if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && psecuritypriv->busetkipkey) {4366union recv_frame *pending_frame;4367int cnt = 0;43684369while ((pending_frame = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue))) {4370cnt++;4371DBG_COUNTER(padapter->rx_logs.core_rx_dequeue);4372recv_func_posthandle(padapter, pending_frame);4373}43744375if (cnt)4376RTW_INFO(FUNC_ADPT_FMT" dequeue %d from uc_swdec_pending_queue\n",4377FUNC_ADPT_ARG(padapter), cnt);4378}43794380DBG_COUNTER(padapter->rx_logs.core_rx);4381ret = recv_func_prehandle(padapter, rframe);43824383if (ret == _SUCCESS) {43844385/* check if need to enqueue into uc_swdec_pending_queue*/4386if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&4387!IS_MCAST(prxattrib->ra) && prxattrib->encrypt > 0 &&4388(prxattrib->bdecrypted == 0 || psecuritypriv->sw_decrypt == _TRUE) &&4389psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPAPSK &&4390!psecuritypriv->busetkipkey) {4391DBG_COUNTER(padapter->rx_logs.core_rx_enqueue);4392rtw_enqueue_recvframe(rframe, &padapter->recvpriv.uc_swdec_pending_queue);4393/* RTW_INFO("%s: no key, enqueue uc_swdec_pending_queue\n", __func__); */43944395if (recvpriv->free_recvframe_cnt < NR_RECVFRAME / 4) {4396/* to prevent from recvframe starvation, get recvframe from uc_swdec_pending_queue to free_recvframe_cnt */4397rframe = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue);4398if (rframe)4399goto do_posthandle;4400}4401goto exit;4402}44034404do_posthandle:4405ret = recv_func_posthandle(padapter, rframe);4406}44074408exit:4409return ret;4410}441144124413s32 rtw_recv_entry(union recv_frame *precvframe)4414{4415_adapter *padapter;4416struct recv_priv *precvpriv;4417s32 ret = _SUCCESS;4418441944204421padapter = precvframe->u.hdr.adapter;44224423precvpriv = &padapter->recvpriv;442444254426ret = recv_func(padapter, precvframe);4427if (ret == _FAIL) {4428goto _recv_entry_drop;4429}443044314432precvpriv->rx_pkts++;443344344435return ret;44364437_recv_entry_drop:44384439#ifdef CONFIG_MP_INCLUDED4440if (padapter->registrypriv.mp_mode == 1)4441padapter->mppriv.rx_pktloss = precvpriv->rx_drop;4442#endif4443444444454446return ret;4447}44484449#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS4450static void rtw_signal_stat_timer_hdl(void *ctx)4451{4452_adapter *adapter = (_adapter *)ctx;4453struct recv_priv *recvpriv = &adapter->recvpriv;44544455u32 tmp_s, tmp_q;4456u8 avg_signal_strength = 0;4457u8 avg_signal_qual = 0;4458u32 num_signal_strength = 0;4459u32 num_signal_qual = 0;4460u8 ratio_pre_stat = 0, ratio_curr_stat = 0, ratio_total = 0, ratio_profile = SIGNAL_STAT_CALC_PROFILE_0;44614462if (adapter->recvpriv.is_signal_dbg) {4463/* update the user specific value, signal_strength_dbg, to signal_strength, rssi */4464adapter->recvpriv.signal_strength = adapter->recvpriv.signal_strength_dbg;4465adapter->recvpriv.rssi = (s8)translate_percentage_to_dbm((u8)adapter->recvpriv.signal_strength_dbg);4466} else {44674468if (recvpriv->signal_strength_data.update_req == 0) { /* update_req is clear, means we got rx */4469avg_signal_strength = recvpriv->signal_strength_data.avg_val;4470num_signal_strength = recvpriv->signal_strength_data.total_num;4471/* after avg_vals are accquired, we can re-stat the signal values */4472recvpriv->signal_strength_data.update_req = 1;4473}44744475if (recvpriv->signal_qual_data.update_req == 0) { /* update_req is clear, means we got rx */4476avg_signal_qual = recvpriv->signal_qual_data.avg_val;4477num_signal_qual = recvpriv->signal_qual_data.total_num;4478/* after avg_vals are accquired, we can re-stat the signal values */4479recvpriv->signal_qual_data.update_req = 1;4480}44814482if (num_signal_strength == 0) {4483if (rtw_get_on_cur_ch_time(adapter) == 04484|| rtw_get_passing_time_ms(rtw_get_on_cur_ch_time(adapter)) < 2 * adapter->mlmeextpriv.mlmext_info.bcn_interval4485)4486goto set_timer;4487}44884489if (check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY) == _TRUE4490|| check_fwstate(&adapter->mlmepriv, _FW_LINKED) == _FALSE4491)4492goto set_timer;44934494#ifdef CONFIG_CONCURRENT_MODE4495if (rtw_mi_buddy_check_fwstate(adapter, _FW_UNDER_SURVEY) == _TRUE)4496goto set_timer;4497#endif44984499if (RTW_SIGNAL_STATE_CALC_PROFILE < SIGNAL_STAT_CALC_PROFILE_MAX)4500ratio_profile = RTW_SIGNAL_STATE_CALC_PROFILE;45014502ratio_pre_stat = signal_stat_calc_profile[ratio_profile][0];4503ratio_curr_stat = signal_stat_calc_profile[ratio_profile][1];4504ratio_total = ratio_pre_stat + ratio_curr_stat;45054506/* update value of signal_strength, rssi, signal_qual */4507tmp_s = (ratio_curr_stat * avg_signal_strength + ratio_pre_stat * recvpriv->signal_strength);4508if (tmp_s % ratio_total)4509tmp_s = tmp_s / ratio_total + 1;4510else4511tmp_s = tmp_s / ratio_total;4512if (tmp_s > 100)4513tmp_s = 100;45144515tmp_q = (ratio_curr_stat * avg_signal_qual + ratio_pre_stat * recvpriv->signal_qual);4516if (tmp_q % ratio_total)4517tmp_q = tmp_q / ratio_total + 1;4518else4519tmp_q = tmp_q / ratio_total;4520if (tmp_q > 100)4521tmp_q = 100;45224523recvpriv->signal_strength = tmp_s;4524recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s);4525recvpriv->signal_qual = tmp_q;45264527#if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 14528RTW_INFO(FUNC_ADPT_FMT" signal_strength:%3u, rssi:%3d, signal_qual:%3u"4529", num_signal_strength:%u, num_signal_qual:%u"4530", on_cur_ch_ms:%d"4531"\n"4532, FUNC_ADPT_ARG(adapter)4533, recvpriv->signal_strength4534, recvpriv->rssi4535, recvpriv->signal_qual4536, num_signal_strength, num_signal_qual4537, rtw_get_on_cur_ch_time(adapter) ? rtw_get_passing_time_ms(rtw_get_on_cur_ch_time(adapter)) : 04538);4539#endif4540}45414542set_timer:4543rtw_set_signal_stat_timer(recvpriv);45444545}4546#endif /* CONFIG_NEW_SIGNAL_STAT_PROCESS */45474548static void rx_process_rssi(_adapter *padapter, union recv_frame *prframe)4549{4550struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;4551#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS4552struct signal_stat *signal_stat = &padapter->recvpriv.signal_strength_data;4553#else /* CONFIG_NEW_SIGNAL_STAT_PROCESS */4554u32 last_rssi, tmp_val;4555#endif /* CONFIG_NEW_SIGNAL_STAT_PROCESS */45564557/* RTW_INFO("process_rssi=> pattrib->rssil(%d) signal_strength(%d)\n ",pattrib->recv_signal_power,pattrib->signal_strength); */4558/* if(pRfd->Status.bPacketToSelf || pRfd->Status.bPacketBeacon) */4559{4560#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS4561if (signal_stat->update_req) {4562signal_stat->total_num = 0;4563signal_stat->total_val = 0;4564signal_stat->update_req = 0;4565}45664567signal_stat->total_num++;4568signal_stat->total_val += pattrib->phy_info.signal_strength;4569signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;4570#else /* CONFIG_NEW_SIGNAL_STAT_PROCESS */45714572/* Adapter->RxStats.RssiCalculateCnt++; */ /* For antenna Test */4573if (padapter->recvpriv.signal_strength_data.total_num++ >= PHY_RSSI_SLID_WIN_MAX) {4574padapter->recvpriv.signal_strength_data.total_num = PHY_RSSI_SLID_WIN_MAX;4575last_rssi = padapter->recvpriv.signal_strength_data.elements[padapter->recvpriv.signal_strength_data.index];4576padapter->recvpriv.signal_strength_data.total_val -= last_rssi;4577}4578padapter->recvpriv.signal_strength_data.total_val += pattrib->phy_info.signal_strength;45794580padapter->recvpriv.signal_strength_data.elements[padapter->recvpriv.signal_strength_data.index++] = pattrib->phy_info.signal_strength;4581if (padapter->recvpriv.signal_strength_data.index >= PHY_RSSI_SLID_WIN_MAX)4582padapter->recvpriv.signal_strength_data.index = 0;458345844585tmp_val = padapter->recvpriv.signal_strength_data.total_val / padapter->recvpriv.signal_strength_data.total_num;45864587if (padapter->recvpriv.is_signal_dbg) {4588padapter->recvpriv.signal_strength = padapter->recvpriv.signal_strength_dbg;4589padapter->recvpriv.rssi = (s8)translate_percentage_to_dbm(padapter->recvpriv.signal_strength_dbg);4590} else {4591padapter->recvpriv.signal_strength = tmp_val;4592padapter->recvpriv.rssi = (s8)translate_percentage_to_dbm(tmp_val);4593}45944595#endif /* CONFIG_NEW_SIGNAL_STAT_PROCESS */4596}4597}45984599static void rx_process_link_qual(_adapter *padapter, union recv_frame *prframe)4600{4601struct rx_pkt_attrib *pattrib;4602#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS4603struct signal_stat *signal_stat;4604#else /* CONFIG_NEW_SIGNAL_STAT_PROCESS */4605u32 last_evm = 0, tmpVal;4606#endif /* CONFIG_NEW_SIGNAL_STAT_PROCESS */46074608if (prframe == NULL || padapter == NULL)4609return;46104611pattrib = &prframe->u.hdr.attrib;4612#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS4613signal_stat = &padapter->recvpriv.signal_qual_data;4614#endif /* CONFIG_NEW_SIGNAL_STAT_PROCESS */46154616/* RTW_INFO("process_link_qual=> pattrib->signal_qual(%d)\n ",pattrib->signal_qual); */46174618#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS4619if (signal_stat->update_req) {4620signal_stat->total_num = 0;4621signal_stat->total_val = 0;4622signal_stat->update_req = 0;4623}46244625signal_stat->total_num++;4626signal_stat->total_val += pattrib->phy_info.signal_quality;4627signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;46284629#else /* CONFIG_NEW_SIGNAL_STAT_PROCESS */4630if (pattrib->phy_info.signal_quality != 0) {4631/* */4632/* 1. Record the general EVM to the sliding window. */4633/* */4634if (padapter->recvpriv.signal_qual_data.total_num++ >= PHY_LINKQUALITY_SLID_WIN_MAX) {4635padapter->recvpriv.signal_qual_data.total_num = PHY_LINKQUALITY_SLID_WIN_MAX;4636last_evm = padapter->recvpriv.signal_qual_data.elements[padapter->recvpriv.signal_qual_data.index];4637padapter->recvpriv.signal_qual_data.total_val -= last_evm;4638}4639padapter->recvpriv.signal_qual_data.total_val += pattrib->phy_info.signal_quality;46404641padapter->recvpriv.signal_qual_data.elements[padapter->recvpriv.signal_qual_data.index++] = pattrib->phy_info.signal_quality;4642if (padapter->recvpriv.signal_qual_data.index >= PHY_LINKQUALITY_SLID_WIN_MAX)4643padapter->recvpriv.signal_qual_data.index = 0;464446454646/* <1> Showed on UI for user, in percentage. */4647tmpVal = padapter->recvpriv.signal_qual_data.total_val / padapter->recvpriv.signal_qual_data.total_num;4648padapter->recvpriv.signal_qual = (u8)tmpVal;46494650}4651#endif /* CONFIG_NEW_SIGNAL_STAT_PROCESS */4652}46534654void rx_process_phy_info(_adapter *padapter, union recv_frame *rframe)4655{4656/* Check RSSI */4657rx_process_rssi(padapter, rframe);46584659/* Check PWDB */4660/* process_PWDB(padapter, rframe); */46614662/* UpdateRxSignalStatistics8192C(Adapter, pRfd); */46634664/* Check EVM */4665rx_process_link_qual(padapter, rframe);4666rtw_store_phy_info(padapter, rframe);4667}46684669void rx_query_phy_status(4670union recv_frame *precvframe,4671u8 *pphy_status)4672{4673PADAPTER padapter = precvframe->u.hdr.adapter;4674struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;4675HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);4676struct phydm_phyinfo_struct *p_phy_info = &pattrib->phy_info;4677u8 *wlanhdr;4678struct phydm_perpkt_info_struct pkt_info;4679u8 *ta, *ra;4680u8 is_ra_bmc;4681struct sta_priv *pstapriv;4682struct sta_info *psta = NULL;4683struct recv_priv *precvpriv = &padapter->recvpriv;4684/* _irqL irqL; */46854686pkt_info.is_packet_match_bssid = _FALSE;4687pkt_info.is_packet_to_self = _FALSE;4688pkt_info.is_packet_beacon = _FALSE;4689pkt_info.ppdu_cnt = pattrib->ppdu_cnt;4690pkt_info.station_id = 0xFF;46914692wlanhdr = get_recvframe_data(precvframe);46934694ta = get_ta(wlanhdr);4695ra = get_ra(wlanhdr);4696is_ra_bmc = IS_MCAST(ra);46974698if (_rtw_memcmp(adapter_mac_addr(padapter), ta, ETH_ALEN) == _TRUE) {4699static systime start_time = 0;47004701#if 0 /*For debug */4702if (IsFrameTypeCtrl(wlanhdr)) {4703RTW_INFO("-->Control frame: Y\n");4704RTW_INFO("-->pkt_len: %d\n", pattrib->pkt_len);4705RTW_INFO("-->Sub Type = 0x%X\n", get_frame_sub_type(wlanhdr));4706}47074708/* Dump first 40 bytes of header */4709int i = 0;47104711for (i = 0; i < 40; i++)4712RTW_INFO("%d: %X\n", i, *((u8 *)wlanhdr + i));47134714RTW_INFO("\n");4715#endif47164717if ((start_time == 0) || (rtw_get_passing_time_ms(start_time) > 5000)) {4718RTW_PRINT("Warning!!! %s: Confilc mac addr!!\n", __func__);4719start_time = rtw_get_current_time();4720}4721precvpriv->dbg_rx_conflic_mac_addr_cnt++;4722} else {4723pstapriv = &padapter->stapriv;4724psta = rtw_get_stainfo(pstapriv, ta);4725if (psta)4726pkt_info.station_id = psta->cmn.mac_id;4727}47284729pkt_info.is_packet_match_bssid = (!IsFrameTypeCtrl(wlanhdr))4730&& (!pattrib->icv_err) && (!pattrib->crc_err)4731&& ((!MLME_IS_MESH(padapter) && _rtw_memcmp(get_hdr_bssid(wlanhdr), get_bssid(&padapter->mlmepriv), ETH_ALEN))4732|| (MLME_IS_MESH(padapter) && psta));47334734pkt_info.is_to_self = (!pattrib->icv_err) && (!pattrib->crc_err)4735&& _rtw_memcmp(ra, adapter_mac_addr(padapter), ETH_ALEN);47364737pkt_info.is_packet_to_self = pkt_info.is_packet_match_bssid4738&& _rtw_memcmp(ra, adapter_mac_addr(padapter), ETH_ALEN);47394740pkt_info.is_packet_beacon = pkt_info.is_packet_match_bssid4741&& (get_frame_sub_type(wlanhdr) == WIFI_BEACON);47424743if (psta && IsFrameTypeData(wlanhdr)) {4744if (is_ra_bmc)4745psta->curr_rx_rate_bmc = pattrib->data_rate;4746else4747psta->curr_rx_rate = pattrib->data_rate;4748}4749pkt_info.data_rate = pattrib->data_rate;47504751odm_phy_status_query(&pHalData->odmpriv, p_phy_info, pphy_status, &pkt_info);47524753/* If bw is initial value, get from phy status */4754if (pattrib->bw == CHANNEL_WIDTH_MAX)4755pattrib->bw = p_phy_info->band_width;47564757{4758precvframe->u.hdr.psta = NULL;4759if (padapter->registrypriv.mp_mode != 1) {4760if ((!MLME_IS_MESH(padapter) && pkt_info.is_packet_match_bssid)4761|| (MLME_IS_MESH(padapter) && psta)) {4762if (psta) {4763precvframe->u.hdr.psta = psta;4764rx_process_phy_info(padapter, precvframe);4765}4766} else if (pkt_info.is_packet_to_self || pkt_info.is_packet_beacon) {4767if (psta)4768precvframe->u.hdr.psta = psta;4769rx_process_phy_info(padapter, precvframe);4770}4771} else {4772#ifdef CONFIG_MP_INCLUDED4773if (padapter->mppriv.brx_filter_beacon == _TRUE) {4774if (pkt_info.is_packet_beacon) {4775RTW_INFO("in MP Rx is_packet_beacon\n");4776if (psta)4777precvframe->u.hdr.psta = psta;4778rx_process_phy_info(padapter, precvframe);4779}4780} else4781#endif4782{4783if (psta)4784precvframe->u.hdr.psta = psta;4785rx_process_phy_info(padapter, precvframe);4786}4787}4788}47894790rtw_odm_parse_rx_phy_status_chinfo(precvframe, pphy_status);4791}4792/*4793* Increase and check if the continual_no_rx_packet of this @param pmlmepriv is larger than MAX_CONTINUAL_NORXPACKET_COUNT4794* @return _TRUE:4795* @return _FALSE:4796*/4797int rtw_inc_and_chk_continual_no_rx_packet(struct sta_info *sta, int tid_index)4798{47994800int ret = _FALSE;4801int value = ATOMIC_INC_RETURN(&sta->continual_no_rx_packet[tid_index]);48024803if (value >= MAX_CONTINUAL_NORXPACKET_COUNT)4804ret = _TRUE;48054806return ret;4807}48084809/*4810* Set the continual_no_rx_packet of this @param pmlmepriv to 04811*/4812void rtw_reset_continual_no_rx_packet(struct sta_info *sta, int tid_index)4813{4814ATOMIC_SET(&sta->continual_no_rx_packet[tid_index], 0);4815}48164817u8 adapter_allow_bmc_data_rx(_adapter *adapter)4818{4819if (check_fwstate(&adapter->mlmepriv, WIFI_MONITOR_STATE | WIFI_MP_STATE) == _TRUE)4820return 1;48214822if (MLME_IS_AP(adapter))4823return 0;48244825if (rtw_linked_check(adapter) == _FALSE)4826return 0;48274828return 1;4829}48304831s32 pre_recv_entry(union recv_frame *precvframe, u8 *pphy_status)4832{4833s32 ret = _SUCCESS;4834u8 *pbuf = precvframe->u.hdr.rx_data;4835u8 *pda = get_ra(pbuf);4836u8 ra_is_bmc = IS_MCAST(pda);4837_adapter *primary_padapter = precvframe->u.hdr.adapter;4838#ifdef CONFIG_CONCURRENT_MODE4839_adapter *iface = NULL;48404841#ifdef CONFIG_MP_INCLUDED4842if (rtw_mp_mode_check(primary_padapter))4843goto bypass_concurrent_hdl;4844#endif48454846if (ra_is_bmc == _FALSE) { /*unicast packets*/4847iface = rtw_get_iface_by_macddr(primary_padapter , pda);4848if (NULL == iface) {4849#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI4850if (_rtw_memcmp(pda, adapter_pno_mac_addr(primary_padapter),4851ETH_ALEN) != _TRUE)4852#endif4853RTW_INFO("%s [WARN] Cannot find appropriate adapter - mac_addr : "MAC_FMT"\n", __func__, MAC_ARG(pda));4854/*rtw_warn_on(1);*/4855} else4856precvframe->u.hdr.adapter = iface;4857} else /* Handle BC/MC Packets */4858rtw_mi_buddy_clone_bcmc_packet(primary_padapter, precvframe, pphy_status);4859bypass_concurrent_hdl:4860#endif /* CONFIG_CONCURRENT_MODE */4861if (primary_padapter->registrypriv.mp_mode != 1) {4862/* skip unnecessary bmc data frame for primary adapter */4863if (ra_is_bmc == _TRUE && GetFrameType(pbuf) == WIFI_DATA_TYPE4864&& !adapter_allow_bmc_data_rx(precvframe->u.hdr.adapter)4865) {4866rtw_free_recvframe(precvframe, &precvframe->u.hdr.adapter->recvpriv.free_recv_queue);4867goto exit;4868}4869}48704871if (pphy_status)4872rx_query_phy_status(precvframe, pphy_status);4873ret = rtw_recv_entry(precvframe);48744875exit:4876return ret;4877}48784879#ifdef CONFIG_RECV_THREAD_MODE4880thread_return rtw_recv_thread(thread_context context)4881{4882_adapter *adapter = (_adapter *)context;4883struct recv_priv *recvpriv = &adapter->recvpriv;4884s32 err = _SUCCESS;4885#ifdef RTW_RECV_THREAD_HIGH_PRIORITY4886#ifdef PLATFORM_LINUX4887struct sched_param param = { .sched_priority = 1 };48884889sched_setscheduler(current, SCHED_FIFO, ¶m);4890#endif /* PLATFORM_LINUX */4891#endif /*RTW_RECV_THREAD_HIGH_PRIORITY*/4892thread_enter("RTW_RECV_THREAD");48934894RTW_INFO(FUNC_ADPT_FMT" enter\n", FUNC_ADPT_ARG(adapter));48954896do {4897err = _rtw_down_sema(&recvpriv->recv_sema);4898if (_FAIL == err) {4899RTW_ERR(FUNC_ADPT_FMT" down recv_sema fail!\n", FUNC_ADPT_ARG(adapter));4900goto exit;4901}49024903if (RTW_CANNOT_RUN(adapter)) {4904RTW_DBG(FUNC_ADPT_FMT "- bDriverStopped(%s) bSurpriseRemoved(%s)\n",4905FUNC_ADPT_ARG(adapter),4906rtw_is_drv_stopped(adapter) ? "True" : "False",4907rtw_is_surprise_removed(adapter) ? "True" : "False");4908goto exit;4909}49104911err = rtw_hal_recv_hdl(adapter);49124913if (err == RTW_RFRAME_UNAVAIL4914|| err == RTW_RFRAME_PKT_UNAVAIL4915) {4916rtw_msleep_os(1);4917_rtw_up_sema(&recvpriv->recv_sema);4918}49194920flush_signals_thread();49214922} while (err != _FAIL);49234924exit:49254926RTW_INFO(FUNC_ADPT_FMT " Exit\n", FUNC_ADPT_ARG(adapter));49274928rtw_thread_wait_stop();49294930return 0;4931}4932#endif /* CONFIG_RECV_THREAD_MODE */49334934#if DBG_RX_BH_TRACKING4935void rx_bh_tk_set_stage(struct recv_priv *recv, u32 s)4936{4937recv->rx_bh_stage = s;4938}49394940void rx_bh_tk_set_buf(struct recv_priv *recv, void *buf, void *data, u32 dlen)4941{4942if (recv->rx_bh_cbuf)4943recv->rx_bh_lbuf = recv->rx_bh_cbuf;4944recv->rx_bh_cbuf = buf;4945if (buf) {4946recv->rx_bh_cbuf_data = data;4947recv->rx_bh_cbuf_dlen = dlen;4948recv->rx_bh_buf_dq_cnt++;4949} else {4950recv->rx_bh_cbuf_data = NULL;4951recv->rx_bh_cbuf_dlen = 0;4952}4953}49544955void rx_bh_tk_set_buf_pos(struct recv_priv *recv, void *pos)4956{4957if (recv->rx_bh_cbuf) {4958recv->rx_bh_cbuf_pos = pos - recv->rx_bh_cbuf_data;4959} else {4960rtw_warn_on(1);4961recv->rx_bh_cbuf_pos = 0;4962}4963}49644965void rx_bh_tk_set_frame(struct recv_priv *recv, void *frame)4966{4967recv->rx_bh_cframe = frame;4968}49694970void dump_rx_bh_tk(void *sel, struct recv_priv *recv)4971{4972RTW_PRINT_SEL(sel, "[RXBHTK]s:%u, buf_dqc:%u, lbuf:%p, cbuf:%p, dlen:%u, pos:%u, cframe:%p\n"4973, recv->rx_bh_stage4974, recv->rx_bh_buf_dq_cnt4975, recv->rx_bh_lbuf4976, recv->rx_bh_cbuf4977, recv->rx_bh_cbuf_dlen4978, recv->rx_bh_cbuf_pos4979, recv->rx_bh_cframe4980);4981}4982#endif /* DBG_RX_BH_TRACKING */4983498449854986