summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/rtl8723as/core/rtw_recv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rtl8723as/core/rtw_recv.c')
-rwxr-xr-xdrivers/net/wireless/rtl8723as/core/rtw_recv.c277
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);
}