diff options
Diffstat (limited to 'drivers/net/wireless/rtl8723as/core/rtw_recv.c')
-rwxr-xr-x | drivers/net/wireless/rtl8723as/core/rtw_recv.c | 277 |
1 files changed, 216 insertions, 61 deletions
diff --git a/drivers/net/wireless/rtl8723as/core/rtw_recv.c b/drivers/net/wireless/rtl8723as/core/rtw_recv.c index e7f8708c2028..05a514ea6926 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_recv.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_recv.c @@ -31,6 +31,10 @@ #include <usb_ops.h> #endif +#ifdef CONFIG_BT_COEXIST +#include <rtl8723a_hal.h> +#endif + #if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS) #error "Shall be Linux or Windows, but not both!\n" @@ -279,7 +283,7 @@ _func_enter_; #ifdef CONFIG_BSD_RX_USE_MBUF m_freem(precvframe->u.hdr.pkt); #else // CONFIG_BSD_RX_USE_MBUF - dev_kfree_skb_any(precvframe->u.hdr.pkt);//free skb by driver + rtw_skb_free(precvframe->u.hdr.pkt);//free skb by driver #endif // CONFIG_BSD_RX_USE_MBUF precvframe->u.hdr.pkt = NULL; } @@ -737,6 +741,9 @@ _func_enter_; return_packet = NULL; } + else{ + prxattrib->bdecrypted = _TRUE; + } //recvframe_chkmic(adapter, precv_frame); //move to recvframme_defrag function _func_exit_; @@ -761,7 +768,6 @@ union recv_frame * portctrl(_adapter *adapter,union recv_frame * precv_frame) _func_enter_; pstapriv = &adapter->stapriv; - psta = rtw_get_stainfo(pstapriv, psta_addr); auth_alg = adapter->securitypriv.dot11AuthAlgrthm; @@ -772,6 +778,8 @@ _func_enter_; prtnframe = NULL; + psta = rtw_get_stainfo(pstapriv, psta_addr); + RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("########portctrl:adapter->securitypriv.dot11AuthAlgrthm=%d\n",adapter->securitypriv.dot11AuthAlgrthm)); if(auth_alg==2) @@ -1739,7 +1747,7 @@ union recv_frame* recvframe_chk_defrag(PADAPTER padapter, union recv_frame *prec sint validate_recv_mgnt_frame(PADAPTER padapter, union recv_frame *precv_frame); sint validate_recv_mgnt_frame(PADAPTER padapter, union recv_frame *precv_frame) { - //struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + //struct mlme_priv *pmlmepriv = &padapter->mlmepriv; RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("+validate_recv_mgnt_frame\n")); @@ -2012,6 +2020,127 @@ _func_exit_; return ret; } +#ifdef CONFIG_IEEE80211W +static sint validate_80211w_mgmt(_adapter *adapter, union recv_frame *precv_frame) +{ + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib; + u8 *ptr = precv_frame->u.hdr.rx_data; + u8 type; + u8 subtype; + + type = GetFrameType(ptr); + subtype = GetFrameSubType(ptr); //bit(7)~bit(2) + + //only support station mode + if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED) + && adapter->securitypriv.binstallBIPkey == _TRUE) + { + //unicast management frame decrypt + if(pattrib->privacy && !(IS_MCAST(GetAddr1Ptr(ptr))) && + (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC || subtype == WIFI_ACTION)) + { + u8 *ppp, *mgmt_DATA; + u32 data_len=0; + ppp = GetAddr2Ptr(ptr); + + pattrib->bdecrypted = 0; + pattrib->encrypt = _AES_; + pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); + //set iv and icv length + SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt); + _rtw_memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN); + _rtw_memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN); + //actual management data frame body + data_len = pattrib->pkt_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; + mgmt_DATA = rtw_zmalloc(data_len); + if(mgmt_DATA == NULL) + { + DBG_871X("%s mgmt allocate fail !!!!!!!!!\n", __FUNCTION__); + goto validate_80211w_fail; + } + /*//dump the packet content before decrypt + { + int pp; + printk("pattrib->pktlen = %d =>", pattrib->pkt_len); + for(pp=0;pp< pattrib->pkt_len; pp++) + printk(" %02x ", ptr[pp]); + printk("\n"); + }*/ + + precv_frame = decryptor(adapter, precv_frame); + //save actual management data frame body + _rtw_memcpy(mgmt_DATA, ptr+pattrib->hdrlen+pattrib->iv_len, data_len); + //overwrite the iv field + _rtw_memcpy(ptr+pattrib->hdrlen, mgmt_DATA, data_len); + //remove the iv and icv length + pattrib->pkt_len = pattrib->pkt_len - pattrib->iv_len - pattrib->icv_len; + rtw_mfree(mgmt_DATA, data_len); + /*//print packet content after decryption + { + int pp; + printk("after decryption pattrib->pktlen = %d @@=>", pattrib->pkt_len); + for(pp=0;pp< pattrib->pkt_len; pp++) + printk(" %02x ", ptr[pp]); + printk("\n"); + }*/ + if(!precv_frame) + { + DBG_871X("%s mgmt descrypt fail !!!!!!!!!\n", __FUNCTION__); + goto validate_80211w_fail; + } + } + else if(IS_MCAST(GetAddr1Ptr(ptr)) && + (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC)) + { + sint BIP_ret = _SUCCESS; + //verify BIP MME IE of broadcast/multicast de-auth/disassoc packet + BIP_ret = rtw_BIP_verify(adapter, (u8 * )precv_frame); + if(BIP_ret == _FAIL) + { + //DBG_871X("802.11w BIP verify fail\n"); + goto validate_80211w_fail; + } + else if(BIP_ret == RTW_RX_HANDLED) + { + //DBG_871X("802.11w recv none protected packet\n"); + //issue sa query request + issue_action_SA_Query(adapter, NULL, 0, 0); + goto validate_80211w_fail; + } + }//802.11w protect + else + { + if(subtype == WIFI_ACTION) + { + //according 802.11-2012 standard, these five types are not robust types + if( ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_PUBLIC && + ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_HT && + ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_UNPROTECTED_WNM && + ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_SELF_PROTECTED && + ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_P2P) + { + DBG_871X("action frame category=%d should robust\n", ptr[WLAN_HDR_A3_LEN]); + goto validate_80211w_fail; + } + } + else if(subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC) + { + DBG_871X("802.11w recv none protected packet\n"); + //issue sa query request + issue_action_SA_Query(adapter, NULL, 0, 0); + goto validate_80211w_fail; + } + } + } + return _SUCCESS; + +validate_80211w_fail: + return _FAIL; + +} +#endif //CONFIG_IEEE80211W + sint validate_recv_frame(_adapter *adapter, union recv_frame *precv_frame); sint validate_recv_frame(_adapter *adapter, union recv_frame *precv_frame) { @@ -2022,7 +2151,6 @@ sint validate_recv_frame(_adapter *adapter, union recv_frame *precv_frame) u8 type; u8 subtype; sint retval = _SUCCESS; - struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib; u8 *ptr = precv_frame->u.hdr.rx_data; @@ -2138,6 +2266,14 @@ _func_enter_; switch (type) { case WIFI_MGT_TYPE: //mgnt +#ifdef CONFIG_IEEE80211W + if(validate_80211w_mgmt(adapter, precv_frame) == _FAIL) + { + retval = _FAIL; + break; + } +#endif //CONFIG_IEEE80211W + retval = validate_recv_mgnt_frame(adapter, precv_frame); if (retval == _FAIL) { @@ -2454,12 +2590,8 @@ static void recvframe_expand_pkt( //3 1. alloc new skb // prepare extra space for 4 bytes alignment -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) // http://www.mail-archive.com/netdev@vger.kernel.org/msg17214.html - ppkt = dev_alloc_skb(alloc_sz); - if (ppkt) ppkt->dev = padapter->pnetdev; -#else - ppkt = netdev_alloc_skb(padapter->pnetdev, alloc_sz); -#endif + ppkt = rtw_skb_alloc(alloc_sz); + if (!ppkt) return; // no way to expand //3 2. Prepare new skb to replace & release old skb @@ -2471,7 +2603,7 @@ static void recvframe_expand_pkt( // copy data to new pkt _rtw_memcpy(skb_put(ppkt, pfhdr->len), pfhdr->rx_data, pfhdr->len); - dev_kfree_skb_any(pfhdr->pkt); + rtw_skb_free(pfhdr->pkt); // attach new pkt to recvframe pfhdr->pkt = ppkt; @@ -2770,7 +2902,7 @@ int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe) /* Allocate new skb for releasing to upper layer */ #ifdef CONFIG_SKB_COPY - sub_skb = dev_alloc_skb(nSubframe_Length + 12); + sub_skb = rtw_skb_alloc(nSubframe_Length + 12); if(sub_skb) { skb_reserve(sub_skb, 12); @@ -2780,7 +2912,7 @@ int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe) else #endif // CONFIG_SKB_COPY { - sub_skb = skb_clone(prframe->u.hdr.pkt, GFP_ATOMIC); + sub_skb = rtw_skb_clone(prframe->u.hdr.pkt); if(sub_skb) { sub_skb->data = pdata; @@ -2789,7 +2921,7 @@ int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe) } else { - DBG_871X("skb_clone() Fail!!! , nr_subframes = %d\n",nr_subframes); + DBG_871X("rtw_skb_clone() Fail!!! , nr_subframes = %d\n",nr_subframes); break; } } @@ -2890,7 +3022,7 @@ int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe) #if 1 // bypass this frame to upper layer!! #else - dev_kfree_skb_any(sub_skb); + rtw_skb_free(sub_skb); continue; #endif } @@ -2910,7 +3042,7 @@ int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe) sub_skb->ip_summed = CHECKSUM_NONE; #endif //CONFIG_TCP_CSUM_OFFLOAD_RX - netif_rx(sub_skb); + rtw_netif_rx(padapter->pnetdev, sub_skb); } #else //PLATFORM_FREEBSD @@ -3151,11 +3283,8 @@ exit: _rtw_init_listhead(&pnrframe_new->u.hdr.list); - #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) // http://www.mail-archive.com/netdev@vger.kernel.org/msg17214.html - pskb_copy = dev_alloc_skb(copy_len+64); - #else - pskb_copy = netdev_alloc_skb(padapter->pnetdev, copy_len + 64); - #endif + pskb_copy = rtw_skb_alloc(copy_len+64); + if(pskb_copy==NULL) { DBG_871X("amsdu_to_msdu:can not all(ocate memory for skb copy\n"); @@ -3230,7 +3359,7 @@ exit: #ifdef PLATFORM_LINUX if(pskb) { - pnrframe_new->u.hdr.pkt = skb_clone(pskb, GFP_ATOMIC); + pnrframe_new->u.hdr.pkt = rtw_skb_clone(pskb); } #endif //PLATFORM_LINUX @@ -3597,8 +3726,9 @@ int recv_indicatepkt_reorder(_adapter *padapter, union recv_frame *prframe) //s1. wlanhdr_to_ethhdr(prframe); - if ((pattrib->qos!=1) /*|| pattrib->priority!=0 || IS_MCAST(pattrib->ra)*/ - || (pattrib->eth_type==0x0806) || (pattrib->ack_policy!=0)) + //if ((pattrib->qos!=1) /*|| pattrib->priority!=0 || IS_MCAST(pattrib->ra)*/ + // || (pattrib->eth_type==0x0806) || (pattrib->ack_policy!=0)) + if (pattrib->qos!=1) { if ((padapter->bDriverStopped == _FALSE) && (padapter->bSurpriseRemoved == _FALSE)) @@ -3863,7 +3993,8 @@ int recv_func_prehandle(_adapter *padapter, union recv_frame *rframe) struct rx_pkt_attrib *pattrib = &rframe->u.hdr.attrib; struct recv_priv *precvpriv = &padapter->recvpriv; _queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; - + + #ifdef CONFIG_MP_INCLUDED struct mlme_priv *pmlmepriv = &padapter->mlmepriv; #endif //CONFIG_MP_INCLUDED @@ -3871,20 +4002,20 @@ int recv_func_prehandle(_adapter *padapter, union recv_frame *rframe) #ifdef CONFIG_MP_INCLUDED if (padapter->registrypriv.mp_mode == 1) { - if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0)) - { if (pattrib->crc_err == 1) + { padapter->mppriv.rx_crcerrpktcount++; + } else + { padapter->mppriv.rx_pktcount++; - + } if (check_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE) == _FALSE) { RT_TRACE(_module_rtl871x_recv_c_, _drv_alert_, ("MP - Not in loopback mode , drop pkt \n")); ret = _FAIL; rtw_free_recvframe(rframe, pfree_recv_queue);//free this recv_frame goto exit; } - } } #endif @@ -4189,41 +4320,65 @@ void rtw_signal_stat_timer_hdl(RTW_TIMER_HDL_ARGS){ recvpriv->signal_qual_data.update_req = 1; } - //update value of signal_strength, rssi, signal_qual - if(check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY) == _FALSE) { - tmp_s = (avg_signal_strength+(_alpha-1)*recvpriv->signal_strength); - if(tmp_s %_alpha) - tmp_s = tmp_s/_alpha + 1; - else - tmp_s = tmp_s/_alpha; - if(tmp_s>100) - tmp_s = 100; + if (num_signal_strength == 0) { + if (rtw_get_on_cur_ch_time(adapter) == 0 + || rtw_get_passing_time_ms(rtw_get_on_cur_ch_time(adapter)) < 2 * adapter->mlmeextpriv.mlmext_info.bcn_interval +#ifdef CONFIG_BT_COEXIST + || ((BTDM_IsBtDisabled(adapter) == _FALSE) && (BT_IsBtInquiryPage(adapter) == _TRUE)) +#endif + ) { + goto set_timer; + } + } - tmp_q = (avg_signal_qual+(_alpha-1)*recvpriv->signal_qual); - if(tmp_q %_alpha) - tmp_q = tmp_q/_alpha + 1; - else - tmp_q = tmp_q/_alpha; - if(tmp_q>100) - tmp_q = 100; - - recvpriv->signal_strength = tmp_s; - recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s); - recvpriv->signal_qual = tmp_q; - - #if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1 - DBG_871X("%s signal_strength:%3u, rssi:%3d, signal_qual:%3u" - ", num_signal_strength:%u, num_signal_qual:%u" - "\n" - , __FUNCTION__ - , recvpriv->signal_strength - , recvpriv->rssi - , recvpriv->signal_qual - , num_signal_strength, num_signal_qual - ); - #endif + if(check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY) == _TRUE + || check_fwstate(&adapter->mlmepriv, _FW_LINKED) == _FALSE + ) { + goto set_timer; } + + #ifdef CONFIG_CONCURRENT_MODE + if (check_buddy_fwstate(adapter, _FW_UNDER_SURVEY) == _TRUE) + goto set_timer; + #endif + + //update value of signal_strength, rssi, signal_qual + tmp_s = (avg_signal_strength+(_alpha-1)*recvpriv->signal_strength); + if(tmp_s %_alpha) + tmp_s = tmp_s/_alpha + 1; + else + tmp_s = tmp_s/_alpha; + if(tmp_s>100) + tmp_s = 100; + + tmp_q = (avg_signal_qual+(_alpha-1)*recvpriv->signal_qual); + if(tmp_q %_alpha) + tmp_q = tmp_q/_alpha + 1; + else + tmp_q = tmp_q/_alpha; + if(tmp_q>100) + tmp_q = 100; + + recvpriv->signal_strength = tmp_s; + recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s); + recvpriv->signal_qual = tmp_q; + + #if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1 + DBG_871X(FUNC_ADPT_FMT" signal_strength:%3u, rssi:%3d, signal_qual:%3u" + ", num_signal_strength:%u, num_signal_qual:%u" + ", on_cur_ch_ms:%d" + "\n" + , FUNC_ADPT_ARG(adapter) + , recvpriv->signal_strength + , recvpriv->rssi + , recvpriv->signal_qual + , num_signal_strength, num_signal_qual + , rtw_get_on_cur_ch_time(adapter) ? rtw_get_passing_time_ms(rtw_get_on_cur_ch_time(adapter)) : 0 + ); + #endif } + +set_timer: rtw_set_signal_stat_timer(recvpriv); } |