diff options
Diffstat (limited to 'drivers/staging/rtl8723au/core')
-rw-r--r-- | drivers/staging/rtl8723au/core/rtw_ap.c | 1738 | ||||
-rw-r--r-- | drivers/staging/rtl8723au/core/rtw_cmd.c | 1470 | ||||
-rw-r--r-- | drivers/staging/rtl8723au/core/rtw_efuse.c | 538 | ||||
-rw-r--r-- | drivers/staging/rtl8723au/core/rtw_ieee80211.c | 855 | ||||
-rw-r--r-- | drivers/staging/rtl8723au/core/rtw_mlme.c | 2314 | ||||
-rw-r--r-- | drivers/staging/rtl8723au/core/rtw_mlme_ext.c | 6187 | ||||
-rw-r--r-- | drivers/staging/rtl8723au/core/rtw_pwrctrl.c | 606 | ||||
-rw-r--r-- | drivers/staging/rtl8723au/core/rtw_recv.c | 2204 | ||||
-rw-r--r-- | drivers/staging/rtl8723au/core/rtw_security.c | 1630 | ||||
-rw-r--r-- | drivers/staging/rtl8723au/core/rtw_sreset.c | 214 | ||||
-rw-r--r-- | drivers/staging/rtl8723au/core/rtw_sta_mgt.c | 439 | ||||
-rw-r--r-- | drivers/staging/rtl8723au/core/rtw_wlan_util.c | 1537 | ||||
-rw-r--r-- | drivers/staging/rtl8723au/core/rtw_xmit.c | 2341 |
13 files changed, 0 insertions, 22073 deletions
diff --git a/drivers/staging/rtl8723au/core/rtw_ap.c b/drivers/staging/rtl8723au/core/rtw_ap.c deleted file mode 100644 index aad686da3cf0..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_ap.c +++ /dev/null @@ -1,1738 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_AP_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <linux/ieee80211.h> -#include <wifi.h> -#include <rtl8723a_cmd.h> -#include <rtl8723a_hal.h> -#include <asm/unaligned.h> -#include <rtw_mlme_ext.h> - -void init_mlme_ap_info23a(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - - spin_lock_init(&pmlmepriv->bcn_update_lock); - - /* for ACL */ - _rtw_init_queue23a(&pacl_list->acl_node_q); - - start_ap_mode23a(padapter); -} - -void free_mlme_ap_info23a(struct rtw_adapter *padapter) -{ - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pmlmepriv->update_bcn = false; - pmlmeext->bstart_bss = false; - - rtw_sta_flush23a(padapter); - - pmlmeinfo->state = MSR_NOLINK; - - /* free_assoc_sta_resources */ - rtw_free_all_stainfo23a(padapter); - - /* free bc/mc sta_info */ - psta = rtw_get_bcmc_stainfo23a(padapter); - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); -} - -static void update_BCNTIM(struct rtw_adapter *padapter) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network; - unsigned char *pie = pnetwork_mlmeext->IEs; - u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL; - uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen; - - p = rtw_get_ie23a(pie, WLAN_EID_TIM, &tim_ielen, - pnetwork_mlmeext->IELength); - if (p != NULL && tim_ielen > 0) { - tim_ielen += 2; - - premainder_ie = p+tim_ielen; - - tim_ie_offset = (int)(p - pie); - - remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen; - - /* append TIM IE from dst_ie offset */ - dst_ie = p; - } else { - tim_ielen = 0; - - /* calculate head_len */ - offset = 0; - - /* get ssid_ie len */ - p = rtw_get_ie23a(pie, WLAN_EID_SSID, - &tmp_len, pnetwork_mlmeext->IELength); - if (p != NULL) - offset += tmp_len+2; - - /* get supported rates len */ - p = rtw_get_ie23a(pie, WLAN_EID_SUPP_RATES, - &tmp_len, pnetwork_mlmeext->IELength); - if (p != NULL) - offset += tmp_len+2; - - /* DS Parameter Set IE, len = 3 */ - offset += 3; - - premainder_ie = pie + offset; - - remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen; - - /* append TIM IE from offset */ - dst_ie = pie + offset; - } - - if (remainder_ielen > 0) { - pbackup_remainder_ie = kmalloc(remainder_ielen, GFP_ATOMIC); - if (pbackup_remainder_ie && premainder_ie) - memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); - } - - *dst_ie++ = WLAN_EID_TIM; - - if ((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fc)) - tim_ielen = 5; - else - tim_ielen = 4; - - *dst_ie++ = tim_ielen; - - *dst_ie++ = 0; /* DTIM count */ - *dst_ie++ = 1; /* DTIM period */ - - if (pstapriv->tim_bitmap & BIT(0)) /* for bc/mc frames */ - *dst_ie++ = BIT(0); /* bitmap ctrl */ - else - *dst_ie++ = 0; - - if (tim_ielen == 4) { - *dst_ie++ = pstapriv->tim_bitmap & 0xff; - } else if (tim_ielen == 5) { - put_unaligned_le16(pstapriv->tim_bitmap, dst_ie); - dst_ie += 2; - } - - /* copy remainder IE */ - if (pbackup_remainder_ie) { - memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); - - kfree(pbackup_remainder_ie); - } - - offset = (uint)(dst_ie - pie); - pnetwork_mlmeext->IELength = offset + remainder_ielen; - - set_tx_beacon_cmd23a(padapter); -} - -static u8 chk_sta_is_alive(struct sta_info *psta) -{ - u8 ret = false; - - if ((psta->sta_stats.last_rx_data_pkts + - psta->sta_stats.last_rx_ctrl_pkts) != - (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts)) - ret = true; - - sta_update_last_rx_pkts(psta); - - return ret; -} - -void expire_timeout_chk23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - u8 updated = 0; - struct sta_info *psta, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 chk_alive_num = 0; - struct sta_info *chk_alive_list[NUM_STA]; - int i; - - spin_lock_bh(&pstapriv->auth_list_lock); - phead = &pstapriv->auth_list; - /* check auth_queue */ - list_for_each_entry_safe(psta, ptmp, phead, auth_list) { - if (psta->expire_to > 0) { - psta->expire_to--; - if (psta->expire_to == 0) { - list_del_init(&psta->auth_list); - pstapriv->auth_list_cnt--; - - DBG_8723A("auth expire %pM\n", psta->hwaddr); - - spin_unlock_bh(&pstapriv->auth_list_lock); - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - spin_lock_bh(&pstapriv->auth_list_lock); - } - } - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - /* check asoc_queue */ - list_for_each_entry_safe(psta, ptmp, phead, asoc_list) { - if (chk_sta_is_alive(psta) || !psta->expire_to) { - psta->expire_to = pstapriv->expire_to; - psta->keep_alive_trycnt = 0; - } else { - psta->expire_to--; - } - - if (psta->expire_to <= 0) { - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (padapter->registrypriv.wifi_spec == 1) { - psta->expire_to = pstapriv->expire_to; - continue; - } - - if (psta->state & WIFI_SLEEP_STATE) { - if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) { - /* - * check if alive by another method - * if station is at ps mode. - */ - psta->expire_to = pstapriv->expire_to; - psta->state |= WIFI_STA_ALIVE_CHK_STATE; - /* - * update bcn with tim_bitmap - * for this station - */ - pstapriv->tim_bitmap |= CHKBIT(psta->aid); - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - - if (!pmlmeext->active_keep_alive_check) - continue; - } - } - - if (pmlmeext->active_keep_alive_check) { - chk_alive_list[chk_alive_num++] = psta; - continue; - } - - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - - DBG_8723A("asoc expire %pM, state = 0x%x\n", - psta->hwaddr, psta->state); - updated = ap_free_sta23a(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING); - } else { - /* - * TODO: Aging mechanism to digest frames in - * sleep_q to avoid running out of xmitframe - */ - if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt) - && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME/pstapriv->asoc_list_cnt)/2) - ) { - DBG_8723A("%s sta:%pM, sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", - __func__, - psta->hwaddr, - psta->sleepq_len, - padapter->xmitpriv.free_xmitframe_cnt, - pstapriv->asoc_list_cnt); - wakeup_sta_to_xmit23a(padapter, psta); - } - } - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - if (chk_alive_num) { - - u8 backup_oper_channel = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - /* - * switch to correct channel of current - * network before issue keep-alive frames - */ - if (rtw_get_oper_ch23a(padapter) != pmlmeext->cur_channel) { - backup_oper_channel = rtw_get_oper_ch23a(padapter); - SelectChannel23a(padapter, pmlmeext->cur_channel); - } - - /* issue null data to check sta alive */ - for (i = 0; i < chk_alive_num; i++) { - - int ret = _FAIL; - - psta = chk_alive_list[i]; - if (!(psta->state & _FW_LINKED)) - continue; - - if (psta->state & WIFI_SLEEP_STATE) - ret = issue_nulldata23a(padapter, psta->hwaddr, 0, 1, 50); - else - ret = issue_nulldata23a(padapter, psta->hwaddr, 0, 3, 50); - - psta->keep_alive_trycnt++; - if (ret == _SUCCESS) { - DBG_8723A("asoc check, sta(%pM) is alive\n", - psta->hwaddr); - psta->expire_to = pstapriv->expire_to; - psta->keep_alive_trycnt = 0; - continue; - } else if (psta->keep_alive_trycnt <= 3) { - DBG_8723A("ack check for asoc expire, keep_alive_trycnt =%d\n", psta->keep_alive_trycnt); - psta->expire_to = 1; - continue; - } - - psta->keep_alive_trycnt = 0; - - DBG_8723A("asoc expire %pM, state = 0x%x\n", - psta->hwaddr, psta->state); - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&psta->asoc_list)) { - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta23a(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - } - - if (backup_oper_channel > 0) /* back to original operation channel */ - SelectChannel23a(padapter, backup_oper_channel); -} - - associated_clients_update23a(padapter, updated); -} - -void add_RATid23a(struct rtw_adapter *padapter, struct sta_info *psta, u8 rssi_level) -{ - int i; - u8 rf_type; - u32 init_rate = 0; - unsigned char sta_band = 0, raid, shortGIrate = false; - unsigned char limit; - unsigned int tx_ra_bitmap = 0; - struct ht_priv *psta_ht = NULL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_network = &pmlmepriv->cur_network.network; - - if (psta) - psta_ht = &psta->htpriv; - else - return; - - if (!(psta->state & _FW_LINKED)) - return; - - /* b/g mode ra_bitmap */ - for (i = 0; i < sizeof(psta->bssrateset); i++) { - if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value23a(psta->bssrateset[i]&0x7f); - } - /* n mode ra_bitmap */ - if (psta_ht->ht_option) { - rf_type = rtl8723a_get_rf_type(padapter); - - if (rf_type == RF_2T2R) - limit = 16; /* 2R */ - else - limit = 8; /* 1R */ - - for (i = 0; i < limit; i++) { - if (psta_ht->ht_cap.mcs.rx_mask[i / 8] & BIT(i % 8)) - tx_ra_bitmap |= BIT(i + 12); - } - - /* max short GI rate */ - shortGIrate = psta_ht->sgi; - } - - if (pcur_network->DSConfig > 14) { - /* 5G band */ - if (tx_ra_bitmap & 0xffff000) - sta_band |= WIRELESS_11_5N | WIRELESS_11A; - else - sta_band |= WIRELESS_11A; - } else { - if (tx_ra_bitmap & 0xffff000) - sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B; - else if (tx_ra_bitmap & 0xff0) - sta_band |= WIRELESS_11G | WIRELESS_11B; - else - sta_band |= WIRELESS_11B; - } - - psta->wireless_mode = sta_band; - - raid = networktype_to_raid23a(sta_band); - init_rate = get_highest_rate_idx23a(tx_ra_bitmap&0x0fffffff)&0x3f; - - if (psta->aid < NUM_STA) { - u8 arg; - - arg = psta->mac_id&0x1f; - - arg |= BIT(7); /* support entry 2~31 */ - - if (shortGIrate == true) - arg |= BIT(5); - - tx_ra_bitmap |= ((raid<<28)&0xf0000000); - - DBG_8723A("%s => mac_id:%d , raid:%d , bitmap = 0x%x, arg = " - "0x%x\n", - __func__, psta->mac_id, raid, tx_ra_bitmap, arg); - - /* bitmap[0:27] = tx_rate_bitmap */ - /* bitmap[28:31]= Rate Adaptive id */ - /* arg[0:4] = macid */ - /* arg[5] = Short GI */ - rtl8723a_add_rateatid(padapter, tx_ra_bitmap, arg, rssi_level); - - if (shortGIrate == true) - init_rate |= BIT(6); - - /* set ra_id, init_rate */ - psta->raid = raid; - psta->init_rate = init_rate; - - } else - DBG_8723A("station aid %d exceed the max number\n", psta->aid); -} - -static void update_bmc_sta(struct rtw_adapter *padapter) -{ - u32 init_rate = 0; - unsigned char network_type, raid; - int i, supportRateNum = 0; - unsigned int tx_ra_bitmap = 0; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_network = &pmlmepriv->cur_network.network; - struct sta_info *psta = rtw_get_bcmc_stainfo23a(padapter); - - if (psta) { - psta->aid = 0; /* default set to 0 */ - psta->mac_id = psta->aid + 1; - - psta->qos_option = 0; - psta->htpriv.ht_option = false; - - psta->ieee8021x_blocked = 0; - - memset((void *)&psta->sta_stats, 0, - sizeof(struct stainfo_stats)); - - /* prepare for add_RATid23a */ - supportRateNum = rtw_get_rateset_len23a((u8 *)&pcur_network->SupportedRates); - network_type = rtw_check_network_type23a((u8 *)&pcur_network->SupportedRates, supportRateNum, 1); - - memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum); - psta->bssratelen = supportRateNum; - - /* b/g mode ra_bitmap */ - for (i = 0; i < supportRateNum; i++) { - if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value23a(psta->bssrateset[i]&0x7f); - } - - if (pcur_network->DSConfig > 14) { - /* force to A mode. 5G doesn't support CCK rates */ - network_type = WIRELESS_11A; - tx_ra_bitmap = 0x150; /* 6, 12, 24 Mbps */ - } else { - /* force to b mode */ - network_type = WIRELESS_11B; - tx_ra_bitmap = 0xf; - } - - raid = networktype_to_raid23a(network_type); - init_rate = get_highest_rate_idx23a(tx_ra_bitmap&0x0fffffff)&0x3f; - - /* ap mode */ - rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, true); - - { - u8 arg; - - arg = psta->mac_id&0x1f; - - arg |= BIT(7); - - tx_ra_bitmap |= ((raid<<28)&0xf0000000); - - DBG_8723A("update_bmc_sta, mask = 0x%x, arg = 0x%x\n", tx_ra_bitmap, arg); - - /* bitmap[0:27] = tx_rate_bitmap */ - /* bitmap[28:31]= Rate Adaptive id */ - /* arg[0:4] = macid */ - /* arg[5] = Short GI */ - rtl8723a_add_rateatid(padapter, tx_ra_bitmap, arg, 0); - } - - /* set ra_id, init_rate */ - psta->raid = raid; - psta->init_rate = init_rate; - - spin_lock_bh(&psta->lock); - psta->state = _FW_LINKED; - spin_unlock_bh(&psta->lock); - - } else - DBG_8723A("add_RATid23a_bmc_sta error!\n"); -} - -/* - * AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode - * MAC_ID = AID+1 for sta in ap/adhoc mode - * MAC_ID = 1 for bc/mc for sta/ap/adhoc - * MAC_ID = 0 for bssid for sta/ap/adhoc - * CAM_ID = 0~3 for default key, cmd_id = macid + 3, macid = aid + 1; - */ -void update_sta_info23a_apmode23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; - struct ht_priv *phtpriv_sta = &psta->htpriv; - /* set intf_tag to if1 */ - - psta->mac_id = psta->aid+1; - DBG_8723A("%s\n", __func__); - - /* ap mode */ - rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, true); - - if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) - psta->ieee8021x_blocked = true; - else - psta->ieee8021x_blocked = false; - - /* update sta's cap */ - - /* ERP */ - VCS_update23a(padapter, psta); - /* HT related cap */ - if (phtpriv_sta->ht_option) { - /* check if sta supports rx ampdu */ - phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable; - - /* check if sta support s Short GI */ - if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) - phtpriv_sta->sgi = true; - - /* bwmode */ - if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40)) { - /* phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_40; */ - phtpriv_sta->bwmode = pmlmeext->cur_bwmode; - phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset; - - } - - psta->qos_option = true; - - } else { - phtpriv_sta->ampdu_enable = false; - - phtpriv_sta->sgi = false; - phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20; - phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - - /* Rx AMPDU */ - send_delba23a(padapter, 0, psta->hwaddr); /* recipient */ - - /* TX AMPDU */ - send_delba23a(padapter, 1, psta->hwaddr); /* originator */ - phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */ - phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */ - - /* todo: init other variables */ - - memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); - - spin_lock_bh(&psta->lock); - psta->state |= _FW_LINKED; - spin_unlock_bh(&psta->lock); -} - -static void update_hw_ht_param(struct rtw_adapter *padapter) -{ - unsigned char max_AMPDU_len; - unsigned char min_MPDU_spacing; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - DBG_8723A("%s\n", __func__); - /* - * handle A-MPDU parameter field - * AMPDU_para [1:0]:Max AMPDU Len => 0:8k, 1:16k, 2:32k, 3:64k - * AMPDU_para [4:2]:Min MPDU Start Spacing - */ - max_AMPDU_len = pmlmeinfo->ht_cap.ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR; - - min_MPDU_spacing = (pmlmeinfo->ht_cap.ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2; - - rtl8723a_set_ampdu_min_space(padapter, min_MPDU_spacing); - rtl8723a_set_ampdu_factor(padapter, max_AMPDU_len); - - /* Config SM Power Save setting */ - pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->ht_cap.cap_info) & - IEEE80211_HT_CAP_SM_PS) >> 2; - if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) - DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__); -} - -static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf) -{ - const u8 *p; - u8 val8, cur_channel, cur_bwmode, cur_ch_offset; - u16 bcn_interval; - u32 acparm; - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct wlan_bssid_ex *pnetwork = &pmlmepriv->cur_network.network; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network; - struct ieee80211_ht_operation *pht_info = NULL; - - bcn_interval = (u16)pnetwork->beacon_interval; - cur_channel = pnetwork->DSConfig; - cur_bwmode = HT_CHANNEL_WIDTH_20; - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - /* - * check if there is wps ie - * if there is wpsie in beacon the hostapd will - * update beacon twice when stating hostapd - * and at first time the security - * ie (RSN/WPA IE) will not include in beacon - */ - if (!cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - pnetwork->IEs, - pnetwork->IELength)) - pmlmeext->bstart_bss = true; - - /* todo: update wmm, ht cap */ - /* pmlmeinfo->WMM_enable; */ - /* pmlmeinfo->HT_enable; */ - if (pmlmepriv->qos_option) - pmlmeinfo->WMM_enable = true; - if (pmlmepriv->htpriv.ht_option) { - pmlmeinfo->WMM_enable = true; - pmlmeinfo->HT_enable = true; - - update_hw_ht_param(padapter); - } - - if (pmlmepriv->cur_network.join_res != true) { - /* - * setting only at first time - * WEP Key will be set before this - * function, do not clear CAM. - */ - if (psecuritypriv->dot11PrivacyAlgrthm != - WLAN_CIPHER_SUITE_WEP40 && - psecuritypriv->dot11PrivacyAlgrthm != - WLAN_CIPHER_SUITE_WEP104) - flush_all_cam_entry23a(padapter); /* clear CAM */ - } - - /* set MSR to AP_Mode */ - rtl8723a_set_media_status(padapter, MSR_AP); - - /* Set BSSID REG */ - hw_var_set_bssid(padapter, pnetwork->MacAddress); - - /* Set EDCA param reg */ - acparm = 0x002F3217; /* VO */ - rtl8723a_set_ac_param_vo(padapter, acparm); - acparm = 0x005E4317; /* VI */ - rtl8723a_set_ac_param_vi(padapter, acparm); - acparm = 0x005ea42b; - rtl8723a_set_ac_param_be(padapter, acparm); - acparm = 0x0000A444; /* BK */ - rtl8723a_set_ac_param_bk(padapter, acparm); - - /* Set Security */ - val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) ? - 0xcc : 0xcf; - rtl8723a_set_sec_cfg(padapter, val8); - - /* Beacon Control related register */ - rtl8723a_set_beacon_interval(padapter, bcn_interval); - - UpdateBrateTbl23a(padapter, pnetwork->SupportedRates); - HalSetBrateCfg23a(padapter, pnetwork->SupportedRates); - - if (!pmlmepriv->cur_network.join_res) { - /* setting only at first time */ - - /* disable dynamic functions, such as high power, DIG */ - - /* turn on all dynamic functions */ - rtl8723a_odm_support_ability_set(padapter, - DYNAMIC_ALL_FUNC_ENABLE); - } - /* set channel, bwmode */ - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pnetwork->IEs, - pnetwork->IELength); - if (p && p[1]) { - pht_info = (struct ieee80211_ht_operation *)(p + 2); - - if (pregpriv->cbw40_enable && pht_info->ht_param & - IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) { - /* switch to the 40M Hz mode */ - cur_bwmode = HT_CHANNEL_WIDTH_40; - switch (pht_info->ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - /* - * pmlmeext->cur_ch_offset = - * HAL_PRIME_CHNL_OFFSET_LOWER; - */ - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - break; - default: - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - } - } - /* - * TODO: need to judge the phy parameters - * on concurrent mode for single phy - */ - set_channel_bwmode23a(padapter, cur_channel, cur_ch_offset, cur_bwmode); - - DBG_8723A("CH =%d, BW =%d, offset =%d\n", cur_channel, cur_bwmode, - cur_ch_offset); - - pmlmeext->cur_channel = cur_channel; - pmlmeext->cur_bwmode = cur_bwmode; - pmlmeext->cur_ch_offset = cur_ch_offset; - pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type; - - /* update cur_wireless_mode */ - update_wireless_mode23a(padapter); - - /* update capability after cur_wireless_mode updated */ - update_capinfo23a(padapter, pnetwork->capability); - - /* let pnetwork_mlmeext == pnetwork_mlme. */ - memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length); - - if (pmlmeext->bstart_bss) { - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - - /* issue beacon frame */ - if (send_beacon23a(padapter) == _FAIL) - DBG_8723A("issue_beacon23a, fail!\n"); - } - - /* update bc/mc sta_info */ - update_bmc_sta(padapter); -} - -int rtw_check_beacon_data23a(struct rtw_adapter *padapter, - struct ieee80211_mgmt *mgmt, unsigned int len) -{ - int ret = _SUCCESS; - u8 *p; - u8 *pHT_caps_ie = NULL; - u8 *pHT_info_ie = NULL; - struct sta_info *psta = NULL; - u16 ht_cap = false; - uint ie_len = 0; - int group_cipher, pairwise_cipher; - u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX]; - int supportRateNum = 0; - u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pbss_network = &pmlmepriv->cur_network.network; - u8 *ie = pbss_network->IEs; - u8 *pbuf = mgmt->u.beacon.variable; - - len -= offsetof(struct ieee80211_mgmt, u.beacon.variable); - /* SSID */ - /* Supported rates */ - /* DS Params */ - /* WLAN_EID_COUNTRY */ - /* ERP Information element */ - /* Extended supported rates */ - /* WPA/WPA2 */ - /* Wi-Fi Wireless Multimedia Extensions */ - /* ht_capab, ht_oper */ - /* WPS IE */ - - DBG_8723A("%s, len =%d\n", __func__, len); - - if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return _FAIL; - - if (len > MAX_IE_SZ) - return _FAIL; - - pbss_network->IELength = len; - - memset(ie, 0, MAX_IE_SZ); - - memcpy(ie, pbuf, pbss_network->IELength); - - if (pbss_network->ifmode != NL80211_IFTYPE_AP && - pbss_network->ifmode != NL80211_IFTYPE_P2P_GO) - return _FAIL; - - pbss_network->Rssi = 0; - - memcpy(pbss_network->MacAddress, myid(&padapter->eeprompriv), ETH_ALEN); - - /* SSID */ - p = rtw_get_ie23a(ie, WLAN_EID_SSID, &ie_len, pbss_network->IELength); - if (p && ie_len > 0) { - memset(&pbss_network->Ssid, 0, sizeof(struct cfg80211_ssid)); - memcpy(pbss_network->Ssid.ssid, (p + 2), ie_len); - pbss_network->Ssid.ssid_len = ie_len; - } - - /* channel */ - channel = 0; - p = rtw_get_ie23a(ie, WLAN_EID_DS_PARAMS, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) - channel = *(p + 2); - - pbss_network->DSConfig = channel; - - memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX); - /* get supported rates */ - p = rtw_get_ie23a(ie, WLAN_EID_SUPP_RATES, &ie_len, - pbss_network->IELength); - if (p) { - memcpy(supportRate, p+2, ie_len); - supportRateNum = ie_len; - } - - /* get ext_supported rates */ - p = rtw_get_ie23a(ie, WLAN_EID_EXT_SUPP_RATES, - &ie_len, pbss_network->IELength); - if (p) { - memcpy(supportRate+supportRateNum, p+2, ie_len); - supportRateNum += ie_len; - } - - network_type = rtw_check_network_type23a(supportRate, - supportRateNum, channel); - - rtw_set_supported_rate23a(pbss_network->SupportedRates, network_type); - - /* parsing ERP_IE */ - p = rtw_get_ie23a(ie, WLAN_EID_ERP_INFO, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) - ERP_IE_handler23a(padapter, p); - - /* update privacy/security */ - if (pbss_network->capability & BIT(4)) - pbss_network->Privacy = 1; - else - pbss_network->Privacy = 0; - - psecuritypriv->wpa_psk = 0; - - /* wpa2 */ - group_cipher = 0; pairwise_cipher = 0; - psecuritypriv->wpa2_group_cipher = 0; - psecuritypriv->wpa2_pairwise_cipher = 0; - p = rtw_get_ie23a(ie, WLAN_EID_RSN, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) { - if (rtw_parse_wpa2_ie23a(p, ie_len+2, &group_cipher, - &pairwise_cipher, NULL) == _SUCCESS) { - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - - psecuritypriv->dot8021xalg = 1; /* psk, todo:802.1x */ - psecuritypriv->wpa_psk |= BIT(1); - - psecuritypriv->wpa2_group_cipher = group_cipher; - psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher; - } - } - - /* wpa */ - ie_len = 0; - group_cipher = 0; - pairwise_cipher = 0; - psecuritypriv->wpa_group_cipher = 0; - psecuritypriv->wpa_pairwise_cipher = 0; - for (p = ie; ; p += (ie_len + 2)) { - p = rtw_get_ie23a(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, - pbss_network->IELength - (ie_len + 2)); - if ((p) && (!memcmp(p+2, RTW_WPA_OUI23A_TYPE, 4))) { - if (rtw_parse_wpa_ie23a(p, ie_len+2, &group_cipher, - &pairwise_cipher, NULL) == _SUCCESS) { - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - - /* psk, todo:802.1x */ - psecuritypriv->dot8021xalg = 1; - - psecuritypriv->wpa_psk |= BIT(0); - - psecuritypriv->wpa_group_cipher = group_cipher; - psecuritypriv->wpa_pairwise_cipher = pairwise_cipher; - } - break; - } - - if (!p || !ie_len) - break; - } - - /* wmm */ - ie_len = 0; - pmlmepriv->qos_option = 0; - if (pregistrypriv->wmm_enable) { - for (p = ie; ; p += (ie_len + 2)) { - p = rtw_get_ie23a(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, - (pbss_network->IELength - - (ie_len + 2))); - if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) { - pmlmepriv->qos_option = 1; - - *(p + 8) |= BIT(7);/* QoS Info:support U-APSD */ - - /* disable all ACM bits since the WMM admission - * control is not supported - */ - *(p + 10) &= ~BIT(4); /* BE */ - *(p + 14) &= ~BIT(4); /* BK */ - *(p + 18) &= ~BIT(4); /* VI */ - *(p + 22) &= ~BIT(4); /* VO */ - break; - } - if ((p == NULL) || (ie_len == 0)) - break; - } - } - /* parsing HT_CAP_IE */ - p = rtw_get_ie23a(ie, WLAN_EID_HT_CAPABILITY, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) { - u8 rf_type; - - struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p+2); - - pHT_caps_ie = p; - - ht_cap = true; - network_type |= WIRELESS_11_24N; - - rf_type = rtl8723a_get_rf_type(padapter); - - if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || - (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) - pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY & (0x07<<2)); - else - pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY&0x00); - - /* set Max Rx AMPDU size to 64K */ - pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_FACTOR & 0x03); - - if (rf_type == RF_1T1R) { - pht_cap->mcs.rx_mask[0] = 0xff; - pht_cap->mcs.rx_mask[1] = 0x0; - } - - memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len); - } - - /* parsing HT_INFO_IE */ - p = rtw_get_ie23a(ie, WLAN_EID_HT_OPERATION, &ie_len, - pbss_network->IELength); - if (p && ie_len > 0) - pHT_info_ie = p; - - pmlmepriv->cur_network.network_type = network_type; - - pmlmepriv->htpriv.ht_option = false; - - /* ht_cap */ - if (pregistrypriv->ht_enable && ht_cap) { - pmlmepriv->htpriv.ht_option = true; - pmlmepriv->qos_option = 1; - - if (pregistrypriv->ampdu_enable == 1) - pmlmepriv->htpriv.ampdu_enable = true; - - HT_caps_handler23a(padapter, pHT_caps_ie); - - HT_info_handler23a(padapter, pHT_info_ie); - } - - pbss_network->Length = get_wlan_bssid_ex_sz(pbss_network); - - /* issue beacon to start bss network */ - start_bss_network(padapter, (u8 *)pbss_network); - - /* alloc sta_info for ap itself */ - psta = rtw_get_stainfo23a(&padapter->stapriv, pbss_network->MacAddress); - if (!psta) { - psta = rtw_alloc_stainfo23a(&padapter->stapriv, - pbss_network->MacAddress, - GFP_KERNEL); - if (!psta) - return _FAIL; - } - /* fix bug of flush_cam_entry at STOP AP mode */ - psta->state |= WIFI_AP_STATE; - rtw_indicate_connect23a(padapter); - - /* for check if already set beacon */ - pmlmepriv->cur_network.join_res = true; - - return ret; -} - -void rtw_set_macaddr_acl23a(struct rtw_adapter *padapter, int mode) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - - DBG_8723A("%s, mode =%d\n", __func__, mode); - - pacl_list->mode = mode; -} - -static void update_bcn_erpinfo_ie(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - unsigned char *p, *ie = pnetwork->IEs; - u32 len = 0; - - DBG_8723A("%s, ERP_enable =%d\n", __func__, pmlmeinfo->ERP_enable); - - if (!pmlmeinfo->ERP_enable) - return; - - /* parsing ERP_IE */ - p = rtw_get_ie23a(ie, WLAN_EID_ERP_INFO, &len, pnetwork->IELength); - if (p && len > 0) { - if (pmlmepriv->num_sta_non_erp == 1) - p[2] |= WLAN_ERP_NON_ERP_PRESENT | - WLAN_ERP_USE_PROTECTION; - else - p[2] &= ~(WLAN_ERP_NON_ERP_PRESENT | - WLAN_ERP_USE_PROTECTION); - - if (pmlmepriv->num_sta_no_short_preamble > 0) - p[2] |= WLAN_ERP_BARKER_PREAMBLE; - else - p[2] &= ~(WLAN_ERP_BARKER_PREAMBLE); - - ERP_IE_handler23a(padapter, p); - } -} - -static void update_bcn_wpa_ie(struct rtw_adapter *padapter) -{ - DBG_8723A("%s\n", __func__); -} - -static void update_bcn_wmm_ie(struct rtw_adapter *padapter) -{ - DBG_8723A("%s\n", __func__); -} - -static void update_bcn_wps_ie(struct rtw_adapter *padapter) -{ - DBG_8723A("%s\n", __func__); -} - -static void update_bcn_p2p_ie(struct rtw_adapter *padapter) -{ -} - -static void update_bcn_vendor_spec_ie(struct rtw_adapter *padapter, u8 *oui) -{ - DBG_8723A("%s\n", __func__); - - if (!memcmp(RTW_WPA_OUI23A_TYPE, oui, 4)) - update_bcn_wpa_ie(padapter); - else if (!memcmp(WMM_OUI23A, oui, 4)) - update_bcn_wmm_ie(padapter); - else if (!memcmp(WPS_OUI23A, oui, 4)) - update_bcn_wps_ie(padapter); - else if (!memcmp(P2P_OUI23A, oui, 4)) - update_bcn_p2p_ie(padapter); - else - DBG_8723A("unknown OUI type!\n"); -} - -void update_beacon23a(struct rtw_adapter *padapter, u8 ie_id, u8 *oui, u8 tx) -{ - struct mlme_priv *pmlmepriv; - struct mlme_ext_priv *pmlmeext; - /* struct mlme_ext_info *pmlmeinfo; */ - - /* DBG_8723A("%s\n", __func__); */ - - if (!padapter) - return; - - pmlmepriv = &padapter->mlmepriv; - pmlmeext = &padapter->mlmeextpriv; - /* pmlmeinfo = &pmlmeext->mlmext_info; */ - - if (false == pmlmeext->bstart_bss) - return; - - spin_lock_bh(&pmlmepriv->bcn_update_lock); - - switch (ie_id) { - case WLAN_EID_TIM: - update_BCNTIM(padapter); - break; - - case WLAN_EID_ERP_INFO: - update_bcn_erpinfo_ie(padapter); - break; - - case WLAN_EID_VENDOR_SPECIFIC: - update_bcn_vendor_spec_ie(padapter, oui); - break; - - default: - break; - } - - pmlmepriv->update_bcn = true; - - spin_unlock_bh(&pmlmepriv->bcn_update_lock); - - if (tx) - set_tx_beacon_cmd23a(padapter); -} - -/* - * op_mode - * Set to 0 (HT pure) under the following conditions - * - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or - * - all STAs in the BSS are 20 MHz HT in 20 MHz BSS - * Set to 1 (HT non-member protection) if there may be non-HT STAs - * in both the primary and the secondary channel - * Set to 2 if only HT STAs are associated in BSS, - * however and at least one 20 MHz HT STA is associated - * Set to 3 (HT mixed mode) when one or more non-HT STAs are associated - * (currently non-GF HT station is considered as non-HT STA also) -*/ -static int rtw_ht_operation_update(struct rtw_adapter *padapter) -{ - u16 cur_op_mode, new_op_mode; - int op_mode_changes = 0; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; - - if (pmlmepriv->htpriv.ht_option) - return 0; - - /* if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) */ - /* return 0; */ - - DBG_8723A("%s current operation mode = 0x%X\n", - __func__, pmlmepriv->ht_op_mode); - - if (!(pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) - && pmlmepriv->num_sta_ht_no_gf) { - pmlmepriv->ht_op_mode |= - IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT; - op_mode_changes++; - } else if ((pmlmepriv->ht_op_mode & - IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) && - pmlmepriv->num_sta_ht_no_gf == 0) { - pmlmepriv->ht_op_mode &= - ~IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT; - op_mode_changes++; - } - - if (!(pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT) && - (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) { - pmlmepriv->ht_op_mode |= IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT; - op_mode_changes++; - } else if ((pmlmepriv->ht_op_mode & - IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT) && - (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) { - pmlmepriv->ht_op_mode &= - ~IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT; - op_mode_changes++; - } - - /* - * Note: currently we switch to the MIXED op mode if HT non-greenfield - * station is associated. Probably it's a theoretical case, since - * it looks like all known HT STAs support greenfield. - */ - if (pmlmepriv->num_sta_no_ht || - (pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)) - new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; - else if ((le16_to_cpu(phtpriv_ap->ht_cap.cap_info) & - IEEE80211_HT_CAP_SUP_WIDTH_20_40) && - pmlmepriv->num_sta_ht_20mhz) - new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; - else if (pmlmepriv->olbc_ht) - new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER; - else - new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; - - cur_op_mode = pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_PROTECTION; - if (cur_op_mode != new_op_mode) { - pmlmepriv->ht_op_mode &= ~IEEE80211_HT_OP_MODE_PROTECTION; - pmlmepriv->ht_op_mode |= new_op_mode; - op_mode_changes++; - } - - DBG_8723A("%s new operation mode = 0x%X changes =%d\n", - __func__, pmlmepriv->ht_op_mode, op_mode_changes); - - return op_mode_changes; -} - -void associated_clients_update23a(struct rtw_adapter *padapter, u8 updated) -{ - /* update associated stations cap. */ - if (updated == true) { - struct list_head *phead; - struct sta_info *psta, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - list_for_each_entry_safe(psta, ptmp, phead, asoc_list) - VCS_update23a(padapter, psta); - spin_unlock_bh(&pstapriv->asoc_list_lock); - } -} - -/* called > TSR LEVEL for USB or SDIO Interface */ -void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - u8 beacon_updated = false; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) { - if (!psta->no_short_preamble_set) { - psta->no_short_preamble_set = 1; - - pmlmepriv->num_sta_no_short_preamble++; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_preamble == 1)) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - - } - } else { - if (psta->no_short_preamble_set) { - psta->no_short_preamble_set = 0; - - pmlmepriv->num_sta_no_short_preamble--; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_preamble == 0)) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - - } - } - - if (psta->flags & WLAN_STA_NONERP) { - if (!psta->nonerp_set) { - psta->nonerp_set = 1; - - pmlmepriv->num_sta_non_erp++; - - if (pmlmepriv->num_sta_non_erp == 1) { - beacon_updated = true; - update_beacon23a(padapter, WLAN_EID_ERP_INFO, NULL, true); - } - } - - } else { - if (psta->nonerp_set) { - psta->nonerp_set = 0; - - pmlmepriv->num_sta_non_erp--; - - if (pmlmepriv->num_sta_non_erp == 0) { - beacon_updated = true; - update_beacon23a(padapter, WLAN_EID_ERP_INFO, NULL, true); - } - } - - } - - if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) { - if (!psta->no_short_slot_time_set) { - psta->no_short_slot_time_set = 1; - - pmlmepriv->num_sta_no_short_slot_time++; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_slot_time == 1)) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - - } - } else { - if (psta->no_short_slot_time_set) { - psta->no_short_slot_time_set = 0; - - pmlmepriv->num_sta_no_short_slot_time--; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_slot_time == 0)) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - } - } - - if (psta->flags & WLAN_STA_HT) { - u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info); - - DBG_8723A("HT: STA %pM HT Capabilities Info: 0x%04x\n", - psta->hwaddr, ht_capab); - - if (psta->no_ht_set) { - psta->no_ht_set = 0; - pmlmepriv->num_sta_no_ht--; - } - - if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) { - if (!psta->no_ht_gf_set) { - psta->no_ht_gf_set = 1; - pmlmepriv->num_sta_ht_no_gf++; - } - DBG_8723A("%s STA %pM - no greenfield, num of non-gf stations %d\n", - __func__, psta->hwaddr, - pmlmepriv->num_sta_ht_no_gf); - } - - if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH_20_40) == 0) { - if (!psta->ht_20mhz_set) { - psta->ht_20mhz_set = 1; - pmlmepriv->num_sta_ht_20mhz++; - } - DBG_8723A("%s STA %pM - 20 MHz HT, num of 20MHz HT STAs %d\n", - __func__, psta->hwaddr, - pmlmepriv->num_sta_ht_20mhz); - } - - } else { - if (!psta->no_ht_set) { - psta->no_ht_set = 1; - pmlmepriv->num_sta_no_ht++; - } - if (pmlmepriv->htpriv.ht_option) { - DBG_8723A("%s STA %pM - no HT, num of non-HT stations %d\n", - __func__, psta->hwaddr, - pmlmepriv->num_sta_no_ht); - } - } - - if (rtw_ht_operation_update(padapter) > 0) { - update_beacon23a(padapter, WLAN_EID_HT_CAPABILITY, NULL, false); - update_beacon23a(padapter, WLAN_EID_HT_OPERATION, NULL, true); - } - - /* update associated stations cap. */ - associated_clients_update23a(padapter, beacon_updated); - - DBG_8723A("%s, updated =%d\n", __func__, beacon_updated); -} - -u8 bss_cap_update_on_sta_leave23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - u8 beacon_updated = false; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!psta) - return beacon_updated; - - if (psta->no_short_preamble_set) { - psta->no_short_preamble_set = 0; - pmlmepriv->num_sta_no_short_preamble--; - if (pmlmeext->cur_wireless_mode > WIRELESS_11B - && pmlmepriv->num_sta_no_short_preamble == 0) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - } - - if (psta->nonerp_set) { - psta->nonerp_set = 0; - pmlmepriv->num_sta_non_erp--; - if (pmlmepriv->num_sta_non_erp == 0) { - beacon_updated = true; - update_beacon23a(padapter, WLAN_EID_ERP_INFO, - NULL, true); - } - } - - if (psta->no_short_slot_time_set) { - psta->no_short_slot_time_set = 0; - pmlmepriv->num_sta_no_short_slot_time--; - if (pmlmeext->cur_wireless_mode > WIRELESS_11B - && pmlmepriv->num_sta_no_short_slot_time == 0) { - beacon_updated = true; - update_beacon23a(padapter, 0xFF, NULL, true); - } - } - - if (psta->no_ht_gf_set) { - psta->no_ht_gf_set = 0; - pmlmepriv->num_sta_ht_no_gf--; - } - - if (psta->no_ht_set) { - psta->no_ht_set = 0; - pmlmepriv->num_sta_no_ht--; - } - - if (psta->ht_20mhz_set) { - psta->ht_20mhz_set = 0; - pmlmepriv->num_sta_ht_20mhz--; - } - - if (rtw_ht_operation_update(padapter) > 0) { - update_beacon23a(padapter, WLAN_EID_HT_CAPABILITY, NULL, false); - update_beacon23a(padapter, WLAN_EID_HT_OPERATION, NULL, true); - } - - /* update associated stations cap. */ - - DBG_8723A("%s, updated =%d\n", __func__, beacon_updated); - - return beacon_updated; -} - -u8 ap_free_sta23a(struct rtw_adapter *padapter, struct sta_info *psta, bool active, u16 reason) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - u8 beacon_updated = false; - - if (!psta) - return beacon_updated; - - if (active) { - /* tear down Rx AMPDU */ - send_delba23a(padapter, 0, psta->hwaddr); /* recipient */ - - /* tear down TX AMPDU */ - send_delba23a(padapter, 1, psta->hwaddr); /* originator */ - - issue_deauth23a(padapter, psta->hwaddr, reason); - } - - psta->htpriv.agg_enable_bitmap = 0x0; /* reset */ - psta->htpriv.candidate_tid_bitmap = 0x0; /* reset */ - - /* report_del_sta_event23a(padapter, psta->hwaddr, reason); */ - - /* clear cam entry / key */ - /* clear_cam_entry23a(padapter, (psta->mac_id + 3)); */ - rtw_clearstakey_cmd23a(padapter, (u8 *)psta, (u8)(psta->mac_id + 3), - true); - - spin_lock_bh(&psta->lock); - psta->state &= ~_FW_LINKED; - spin_unlock_bh(&psta->lock); - - rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason); - - report_del_sta_event23a(padapter, psta->hwaddr, reason); - - beacon_updated = bss_cap_update_on_sta_leave23a(padapter, psta); - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - return beacon_updated; -} - -int rtw_sta_flush23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - struct sta_info *psta, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - u8 chk_alive_num = 0; - struct sta_info *chk_alive_list[NUM_STA]; - int i; - - DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name); - - if ((pmlmeinfo->state&0x03) != MSR_AP) - return 0; - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - list_for_each_entry_safe(psta, ptmp, phead, asoc_list) { - /* Remove sta from asoc_list */ - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - - /* Keep sta for ap_free_sta23a() beyond this asoc_list loop */ - chk_alive_list[chk_alive_num++] = psta; - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - /* For each sta in chk_alive_list, call ap_free_sta23a */ - for (i = 0; i < chk_alive_num; i++) - ap_free_sta23a(padapter, chk_alive_list[i], true, - WLAN_REASON_DEAUTH_LEAVING); - - issue_deauth23a(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING); - - associated_clients_update23a(padapter, true); - - return 0; -} - -/* called > TSR LEVEL for USB or SDIO Interface */ -void sta_info_update23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - int flags = psta->flags; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - /* update wmm cap. */ - if (WLAN_STA_WME&flags) - psta->qos_option = 1; - else - psta->qos_option = 0; - - if (pmlmepriv->qos_option == 0) - psta->qos_option = 0; - - /* update 802.11n ht cap. */ - if (WLAN_STA_HT&flags) { - psta->htpriv.ht_option = true; - psta->qos_option = 1; - } else { - psta->htpriv.ht_option = false; - } - - if (!pmlmepriv->htpriv.ht_option) - psta->htpriv.ht_option = false; - - update_sta_info23a_apmode23a(padapter, psta); -} - -/* called >= TSR LEVEL for USB or SDIO Interface */ -void ap_sta_info_defer_update23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - if (psta->state & _FW_LINKED) { - /* add ratid */ - add_RATid23a(padapter, psta, 0);/* DM_RATR_STA_INIT */ - } -} - -/* restore hw setting from sw data structures */ -void rtw_ap_restore_network(struct rtw_adapter *padapter) -{ - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta, *ptmp; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct list_head *phead; - u8 chk_alive_num = 0; - struct sta_info *chk_alive_list[NUM_STA]; - int i; - - rtw_setopmode_cmd23a(padapter, NL80211_IFTYPE_AP); - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - start_bss_network(padapter, (u8 *)&mlmepriv->cur_network.network); - - if (padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_TKIP || - padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) { - /* restore group key, WEP keys is restored in ips_leave23a() */ - rtw_set_key23a(padapter, psecuritypriv, - psecuritypriv->dot118021XGrpKeyid, 0); - } - - /* per sta pairwise key and settings */ - if (padapter->securitypriv.dot11PrivacyAlgrthm != - WLAN_CIPHER_SUITE_TKIP && - padapter->securitypriv.dot11PrivacyAlgrthm != - WLAN_CIPHER_SUITE_CCMP) { - return; - } - - spin_lock_bh(&pstapriv->asoc_list_lock); - phead = &pstapriv->asoc_list; - list_for_each_entry_safe(psta, ptmp, phead, asoc_list) - chk_alive_list[chk_alive_num++] = psta; - spin_unlock_bh(&pstapriv->asoc_list_lock); - - for (i = 0; i < chk_alive_num; i++) { - psta = chk_alive_list[i]; - - if (psta->state & _FW_LINKED) { - Update_RA_Entry23a(padapter, psta); - /* pairwise key */ - rtw_setstakey_cmd23a(padapter, (unsigned char *)psta, true); - } - } -} - -void start_ap_mode23a(struct rtw_adapter *padapter) -{ - int i; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - - pmlmepriv->update_bcn = false; - - /* init_mlme_ap_info23a(padapter); */ - pmlmeext->bstart_bss = false; - - pmlmepriv->num_sta_non_erp = 0; - - pmlmepriv->num_sta_no_short_slot_time = 0; - - pmlmepriv->num_sta_no_short_preamble = 0; - - pmlmepriv->num_sta_ht_no_gf = 0; - pmlmepriv->num_sta_no_ht = 0; - pmlmepriv->num_sta_ht_20mhz = 0; - - pmlmepriv->olbc = false; - - pmlmepriv->olbc_ht = false; - - pmlmepriv->ht_op_mode = 0; - - for (i = 0; i < NUM_STA; i++) - pstapriv->sta_aid[i] = NULL; - - /* for ACL */ - INIT_LIST_HEAD(&pacl_list->acl_node_q.queue); - pacl_list->num = 0; - pacl_list->mode = 0; - for (i = 0; i < NUM_ACL; i++) { - INIT_LIST_HEAD(&pacl_list->aclnode[i].list); - pacl_list->aclnode[i].valid = false; - } -} - -void stop_ap_mode23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - struct rtw_wlan_acl_node *paclnode, *ptmp; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q; - - pmlmepriv->update_bcn = false; - pmlmeext->bstart_bss = false; - - /* - * reset and init security priv , this can - * refine with rtw_reset_securitypriv23a - */ - memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv)); - padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; - padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled; - - /* for ACL */ - spin_lock_bh(&pacl_node_q->lock); - phead = get_list_head(pacl_node_q); - list_for_each_entry_safe(paclnode, ptmp, phead, list) { - if (paclnode->valid == true) { - paclnode->valid = false; - list_del_init(&paclnode->list); - pacl_list->num--; - } - } - spin_unlock_bh(&pacl_node_q->lock); - - DBG_8723A("%s, free acl_node_queue, num =%d\n", - __func__, pacl_list->num); - - rtw_sta_flush23a(padapter); - - /* free_assoc_sta_resources */ - rtw_free_all_stainfo23a(padapter); - - psta = rtw_get_bcmc_stainfo23a(padapter); - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(padapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - rtw_init_bcmc_stainfo23a(padapter); - - rtw23a_free_mlme_priv_ie_data(pmlmepriv); -} diff --git a/drivers/staging/rtl8723au/core/rtw_cmd.c b/drivers/staging/rtl8723au/core/rtw_cmd.c deleted file mode 100644 index cd4e0f05d82f..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_cmd.c +++ /dev/null @@ -1,1470 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_CMD_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <recv_osdep.h> -#include <mlme_osdep.h> -#include <rtl8723a_cmd.h> -#include <rtw_sreset.h> - -static struct cmd_hdl wlancmds[] = { - GEN_DRV_CMD_HANDLER(0, NULL) /*0*/ - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_DRV_CMD_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) /*10*/ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), join_cmd_hdl23a) /*14*/ - GEN_MLME_EXT_HANDLER(sizeof(struct disconnect_parm), disconnect_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct wlan_bssid_ex), createbss_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct setopmode_parm), setopmode_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl23a) /*18*/ - GEN_MLME_EXT_HANDLER(sizeof(struct setauth_parm), setauth_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct setkey_parm), setkey_hdl23a) /*20*/ - GEN_MLME_EXT_HANDLER(sizeof(struct set_stakey_parm), set_stakey_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct set_assocsta_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct del_assocsta_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct setstapwrstate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct setbasicrate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct getbasicrate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct setdatarate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct getdatarate_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct setphyinfo_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct getphyinfo_parm), NULL) /*30*/ - GEN_MLME_EXT_HANDLER(sizeof(struct setphy_parm), NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct getphy_parm), NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) /*40*/ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl23a) - GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl23a) /* 46 */ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) /*50*/ - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(0, NULL) - GEN_MLME_EXT_HANDLER(sizeof(struct Tx_Beacon_param), tx_beacon_hdl23a) /*55*/ - - GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl23a) /*56*/ - GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl23a) /*57*/ - - GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl23a) /*58*/ - GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl23a) /*59*/ - GEN_MLME_EXT_HANDLER(sizeof(struct LedBlink_param), led_blink_hdl23a) /*60*/ - - GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param), set_csa_hdl23a) /*61*/ - GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param), tdls_hdl23a) /*62*/ -}; - -struct _cmd_callback rtw_cmd_callback[] = { - {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/ - {GEN_CMD_CODE(_Write_MACREG), NULL}, - {GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback23a}, - {GEN_CMD_CODE(_Write_BBREG), NULL}, - {GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback23a}, - {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/ - {GEN_CMD_CODE(_Read_EEPROM), NULL}, - {GEN_CMD_CODE(_Write_EEPROM), NULL}, - {GEN_CMD_CODE(_Read_EFUSE), NULL}, - {GEN_CMD_CODE(_Write_EFUSE), NULL}, - - {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/ - {GEN_CMD_CODE(_Write_CAM), NULL}, - {GEN_CMD_CODE(_setBCNITV), NULL}, - {GEN_CMD_CODE(_setMBIDCFG), NULL}, - {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd23a_callback}, /*14*/ - {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd23a_callback}, /*15*/ - {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd23a_callback}, - {GEN_CMD_CODE(_SetOpMode), NULL}, - {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback23a}, /*18*/ - {GEN_CMD_CODE(_SetAuth), NULL}, - - {GEN_CMD_CODE(_SetKey), NULL}, /*20*/ - {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback23a}, - {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback23a}, - {GEN_CMD_CODE(_DelAssocSta), NULL}, - {GEN_CMD_CODE(_SetStaPwrState), NULL}, - {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/ - {GEN_CMD_CODE(_GetBasicRate), NULL}, - {GEN_CMD_CODE(_SetDataRate), NULL}, - {GEN_CMD_CODE(_GetDataRate), NULL}, - {GEN_CMD_CODE(_SetPhyInfo), NULL}, - - {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/ - {GEN_CMD_CODE(_SetPhy), NULL}, - {GEN_CMD_CODE(_GetPhy), NULL}, - {GEN_CMD_CODE(_readRssi), NULL}, - {GEN_CMD_CODE(_readGain), NULL}, - {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/ - {GEN_CMD_CODE(_SetPwrMode), NULL}, - {GEN_CMD_CODE(_JoinbssRpt), NULL}, - {GEN_CMD_CODE(_SetRaTable), NULL}, - {GEN_CMD_CODE(_GetRaTable), NULL}, - - {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/ - {GEN_CMD_CODE(_GetDTMReport), NULL}, - {GEN_CMD_CODE(_GetTXRateStatistics), NULL}, - {GEN_CMD_CODE(_SetUsbSuspend), NULL}, - {GEN_CMD_CODE(_SetH2cLbk), NULL}, - {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/ - {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/ - {GEN_CMD_CODE(_SetTxPower), NULL}, - {GEN_CMD_CODE(_SwitchAntenna), NULL}, - {GEN_CMD_CODE(_SetCrystalCap), NULL}, - {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/ - - {GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/ - {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL}, - {GEN_CMD_CODE(_SetContinuousTx), NULL}, - {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/ - {GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/ - - {GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/ - {GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/ - {GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/ - {GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/ - {GEN_CMD_CODE(_LedBlink), NULL},/*60*/ - - {GEN_CMD_CODE(_SetChannelSwitch), NULL},/*61*/ - {GEN_CMD_CODE(_TDLS), NULL},/*62*/ -}; - -/* -Caller and the rtw_cmd_thread23a can protect cmd_q by spin_lock. -No irqsave is necessary. -*/ - -int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv) -{ - int res = _SUCCESS; - - pcmdpriv->cmd_issued_cnt = 0; - pcmdpriv->cmd_done_cnt = 0; - pcmdpriv->rsp_cnt = 0; - - pcmdpriv->wq = alloc_workqueue("rtl8723au_cmd", 0, 1); - if (!pcmdpriv->wq) - res = _FAIL; - - return res; -} - -/* forward definition */ - -static void rtw_irq_work(struct work_struct *work); - -u32 rtw_init_evt_priv23a(struct evt_priv *pevtpriv) -{ - pevtpriv->wq = alloc_workqueue("rtl8723au_evt", 0, 1); - - INIT_WORK(&pevtpriv->irq_wk, rtw_irq_work); - - return _SUCCESS; -} - -void rtw_free_evt_priv23a(struct evt_priv *pevtpriv) -{ - cancel_work_sync(&pevtpriv->irq_wk); -} - -static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) -{ - /* set to true to allow enqueuing cmd when hw_init_completed is false */ - u8 bAllow = false; - - if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan)) - bAllow = true; - - if (pcmdpriv->padapter->hw_init_completed == false && bAllow == false) - return _FAIL; - return _SUCCESS; -} - -static void rtw_cmd_work(struct work_struct *work); - -int rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) -{ - int res = _FAIL; - - if (!cmd_obj) - goto exit; - - cmd_obj->padapter = pcmdpriv->padapter; - - res = rtw_cmd_filter(pcmdpriv, cmd_obj); - if (res == _FAIL) { - rtw_free_cmd_obj23a(cmd_obj); - goto exit; - } - - INIT_WORK(&cmd_obj->work, rtw_cmd_work); - - res = queue_work(pcmdpriv->wq, &cmd_obj->work); - - if (!res) { - netdev_err(pcmdpriv->padapter->pnetdev, - "%s: Call to queue_work() failed\n", __func__); - res = _FAIL; - } else - res = _SUCCESS; -exit: - - return res; -} - -void rtw_free_cmd_obj23a(struct cmd_obj *pcmd) -{ - - if (pcmd->cmdcode != _JoinBss_CMD_ && - pcmd->cmdcode != _CreateBss_CMD_) { - /* free parmbuf in cmd_obj */ - kfree(pcmd->parmbuf); - } - - if (pcmd->rsp) { - if (pcmd->rspsz != 0) { - /* free rsp in cmd_obj */ - kfree(pcmd->rsp); - } - } - - kfree(pcmd); -} - -static void rtw_cmd_work(struct work_struct *work) -{ - int (*cmd_hdl)(struct rtw_adapter *padapter, const u8 *pbuf); - void (*pcmd_callback)(struct rtw_adapter *dev, struct cmd_obj *pcmd); - struct cmd_priv *pcmdpriv; - struct cmd_obj *pcmd = container_of(work, struct cmd_obj, work); - - pcmdpriv = &pcmd->padapter->cmdpriv; - - if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) { - pcmd->res = H2C_DROPPED; - goto post_process; - } - - pcmdpriv->cmd_issued_cnt++; - - pcmd->cmdsz = ALIGN(pcmd->cmdsz, 4); - - if (pcmd->cmdcode < (sizeof(wlancmds)/sizeof(struct cmd_hdl))) { - cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns; - - if (cmd_hdl) - pcmd->res = cmd_hdl(pcmd->padapter, pcmd->parmbuf); - else - pcmd->res = H2C_DROPPED; - } else - pcmd->res = H2C_PARAMETERS_ERROR; - -post_process: - /* call callback function for post-processed */ - if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) { - pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback; - if (!pcmd_callback) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - "mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", - pcmd_callback, pcmd->cmdcode); - rtw_free_cmd_obj23a(pcmd); - } else { - /* need consider that free cmd_obj in - rtw_cmd_callback */ - pcmd_callback(pcmd->padapter, pcmd); - } - } else { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "%s: cmdcode = 0x%x callback not defined!\n", - __func__, pcmd->cmdcode); - rtw_free_cmd_obj23a(pcmd); - } -} - - -int rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter, - struct cfg80211_ssid *ssid, int ssid_num, - struct rtw_ieee80211_channel *ch, int ch_num) -{ - int res = _FAIL; - struct cmd_obj *ph2c; - struct sitesurvey_parm *psurveyPara; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SCAN, 1); - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) - return _FAIL; - - psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC); - if (!psurveyPara) { - kfree(ph2c); - return _FAIL; - } - - rtw_free_network_queue23a(padapter); - - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - "%s: flush network queue\n", __func__); - - init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, - GEN_CMD_CODE(_SiteSurvey)); - - /* psurveyPara->bsslimit = 48; */ - psurveyPara->scan_mode = pmlmepriv->scan_mode; - - /* prepare ssid list */ - if (ssid) { - int i; - - for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) { - if (ssid[i].ssid_len) { - memcpy(&psurveyPara->ssid[i], &ssid[i], - sizeof(struct cfg80211_ssid)); - psurveyPara->ssid_num++; - } - } - } - - /* prepare channel list */ - if (ch) { - int i; - - for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) { - if (ch[i].hw_value && - !(ch[i].flags & IEEE80211_CHAN_DISABLED)) { - memcpy(&psurveyPara->ch[i], &ch[i], - sizeof(struct rtw_ieee80211_channel)); - psurveyPara->ch_num++; - } - } - } - - set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - - if (res == _SUCCESS) { - mod_timer(&pmlmepriv->scan_to_timer, jiffies + - msecs_to_jiffies(SCANNING_TIMEOUT)); - - pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */ - } else - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - - return res; -} - -void rtw_getbbrfreg_cmdrsp_callback23a(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - kfree(pcmd->parmbuf); - kfree(pcmd); -} - -int rtw_createbss_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *pcmd; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pdev_network; - u8 res = _SUCCESS; - - pdev_network = &padapter->registrypriv.dev_network; - - if (pmlmepriv->assoc_ssid.ssid_len == 0) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - "createbss for Any SSid:%s\n", - pmlmepriv->assoc_ssid.ssid); - } else { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - "createbss for SSid:%s\n", - pmlmepriv->assoc_ssid.ssid); - } - - pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd) { - res = _FAIL; - goto exit; - } - - pcmd->cmdcode = _CreateBss_CMD_; - pcmd->parmbuf = (unsigned char *)pdev_network; - pcmd->cmdsz = get_wlan_bssid_ex_sz(pdev_network); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - pdev_network->Length = pcmd->cmdsz; - - res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); - -exit: - - return res; -} - -int rtw_joinbss_cmd23a(struct rtw_adapter *padapter, - struct wlan_network *pnetwork) -{ - int res = _SUCCESS; - struct wlan_bssid_ex *psecnetwork; - struct cmd_obj *pcmd; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - enum nl80211_iftype ifmode; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - ifmode = pnetwork->network.ifmode; - - if (pmlmepriv->assoc_ssid.ssid_len == 0) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, - "+Join cmd: Any SSid\n"); - } else { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, - "+Join cmd: SSid =[%s]\n", - pmlmepriv->assoc_ssid.ssid); - } - - pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd) { - res = _FAIL; - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "rtw_joinbss_cmd23a: memory allocate for cmd_obj fail!!!\n"); - goto exit; - } - - /* for hidden ap to set fw_state here */ - if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) { - switch (ifmode) { - case NL80211_IFTYPE_ADHOC: - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - set_fwstate(pmlmepriv, WIFI_STATION_STATE); - break; - default: - break; - } - } - - psecnetwork = &psecuritypriv->sec_bss; - if (!psecnetwork) { - kfree(pcmd); - res = _FAIL; - - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "rtw_joinbss_cmd23a :psecnetwork == NULL!!!\n"); - - goto exit; - } - - memset(psecnetwork, 0, sizeof(struct wlan_bssid_ex)); - - memcpy(psecnetwork, &pnetwork->network, - get_wlan_bssid_ex_sz(&pnetwork->network)); - - psecnetwork->IELength = 0; - /* Added by Albert 2009/02/18 */ - /* If the the driver wants to use the bssid to create the - * connection. If not, we have to copy the connecting AP's - * MAC address to it so that the driver just has the bssid - * information for PMKIDList searching. */ - - if (pmlmepriv->assoc_by_bssid == false) - ether_addr_copy(&pmlmepriv->assoc_bssid[0], - &pnetwork->network.MacAddress[0]); - - psecnetwork->IELength = - rtw_restruct_sec_ie23a(padapter, &pnetwork->network.IEs[0], - &psecnetwork->IEs[0], - pnetwork->network.IELength); - - pmlmepriv->qos_option = 0; - - if (pregistrypriv->wmm_enable) { - u32 tmp_len; - - tmp_len = rtw_restruct_wmm_ie23a(padapter, - &pnetwork->network.IEs[0], - &psecnetwork->IEs[0], - pnetwork->network.IELength, - psecnetwork->IELength); - - if (psecnetwork->IELength != tmp_len) { - psecnetwork->IELength = tmp_len; - /* There is WMM IE in this corresp. beacon */ - pmlmepriv->qos_option = 1; - } else { - /* There is no WMM IE in this corresp. beacon */ - pmlmepriv->qos_option = 0; - } - } - - phtpriv->ht_option = false; - if (pregistrypriv->ht_enable) { - u32 algo = padapter->securitypriv.dot11PrivacyAlgrthm; - /* Added by Albert 2010/06/23 */ - /* For the WEP mode, we will use the bg mode to do - the connection to avoid some IOT issue. */ - /* Especially for Realtek 8192u SoftAP. */ - if (algo != WLAN_CIPHER_SUITE_WEP40 && - algo != WLAN_CIPHER_SUITE_WEP104 && - algo != WLAN_CIPHER_SUITE_TKIP) { - /* rtw_restructure_ht_ie23a */ - rtw_restructure_ht_ie23a(padapter, - &pnetwork->network.IEs[0], - &psecnetwork->IEs[0], - pnetwork->network.IELength, - &psecnetwork->IELength); - } - } - - pmlmeinfo->assoc_AP_vendor = - check_assoc_AP23a(pnetwork->network.IEs, - pnetwork->network.IELength); - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA) - padapter->pwrctrlpriv.smart_ps = 0; - else - padapter->pwrctrlpriv.smart_ps = - padapter->registrypriv.smart_ps; - - DBG_8723A("%s: smart_ps =%d\n", __func__, - padapter->pwrctrlpriv.smart_ps); - - /* get cmdsz before endian conversion */ - pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork); - - pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */ - pcmd->parmbuf = (unsigned char *)psecnetwork; - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); -exit: - - return res; -} - -int rtw_disassoc_cmd23a(struct rtw_adapter *padapter, u32 deauth_timeout_ms, - bool enqueue) -{ - struct cmd_obj *cmdobj = NULL; - struct disconnect_parm *param = NULL; - struct cmd_priv *cmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, - "+rtw_disassoc_cmd23a\n"); - - /* prepare cmd parameter */ - param = kzalloc(sizeof(*param), GFP_ATOMIC); - if (param == NULL) { - res = _FAIL; - goto exit; - } - param->deauth_timeout_ms = deauth_timeout_ms; - - if (enqueue) { - /* need enqueue, prepare cmd_obj and enqueue */ - cmdobj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!cmdobj) { - res = _FAIL; - kfree(param); - goto exit; - } - init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_); - res = rtw_enqueue_cmd23a(cmdpriv, cmdobj); - } else { - /* no need to enqueue, do the cmd hdl directly and - free cmd parameter */ - if (disconnect_hdl23a(padapter, (u8 *)param) != H2C_SUCCESS) - res = _FAIL; - kfree(param); - } - -exit: - return res; -} - -int rtw_setopmode_cmd23a(struct rtw_adapter *padapter, - enum nl80211_iftype ifmode) -{ - struct cmd_obj *ph2c; - struct setopmode_parm *psetop; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!ph2c) { - res = false; - goto exit; - } - psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL); - - if (!psetop) { - kfree(ph2c); - res = false; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); - psetop->mode = ifmode; - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); -exit: - return res; -} - -int rtw_setstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 unicast_key) -{ - struct cmd_obj *ph2c; - struct set_stakey_parm *psetstakey_para; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct set_stakey_rsp *psetstakey_rsp = NULL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sta_info *sta = (struct sta_info *)psta; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL); - if (!psetstakey_para) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL); - if (!psetstakey_rsp) { - kfree(ph2c); - kfree(psetstakey_para); - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); - ph2c->rsp = (u8 *) psetstakey_rsp; - ph2c->rspsz = sizeof(struct set_stakey_rsp); - - ether_addr_copy(psetstakey_para->addr, sta->hwaddr); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - psetstakey_para->algorithm = - (unsigned char)psecuritypriv->dot11PrivacyAlgrthm; - } else { - GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, - false); - } - - if (unicast_key == true) { - memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16); - } else { - int idx = psecuritypriv->dot118021XGrpKeyid; - - memcpy(&psetstakey_para->key, - &psecuritypriv->dot118021XGrpKey[idx].skey, 16); - } - - /* jeff: set this because at least sw key is ready */ - padapter->securitypriv.busetkipkey = 1; - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - -exit: - - return res; -} - -int rtw_clearstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 entry, - u8 enqueue) -{ - struct cmd_obj *ph2c; - struct set_stakey_parm *psetstakey_para; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct set_stakey_rsp *psetstakey_rsp = NULL; - struct sta_info *sta = (struct sta_info *)psta; - int res = _SUCCESS; - - if (!enqueue) { - clear_cam_entry23a(padapter, entry); - } else { - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), - GFP_KERNEL); - if (!psetstakey_para) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), - GFP_KERNEL); - if (!psetstakey_rsp) { - kfree(ph2c); - kfree(psetstakey_para); - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, - _SetStaKey_CMD_); - ph2c->rsp = (u8 *) psetstakey_rsp; - ph2c->rspsz = sizeof(struct set_stakey_rsp); - - ether_addr_copy(psetstakey_para->addr, sta->hwaddr); - - psetstakey_para->algorithm = 0; - - psetstakey_para->id = entry; - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - } -exit: - return res; -} - -int rtw_addbareq_cmd23a(struct rtw_adapter *padapter, u8 tid, u8 *addr) -{ - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct cmd_obj *ph2c; - struct addBaReq_parm *paddbareq_parm; - int res = _SUCCESS; - - if (tid >= MAXTID) { - res = _FAIL; - goto exit; - } - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC); - if (!paddbareq_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - paddbareq_parm->tid = tid; - ether_addr_copy(paddbareq_parm->addr, addr); - - init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, - GEN_CMD_CODE(_AddBAReq)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); -exit: - return res; -} - -int rtw_dynamic_chk_wk_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID; - pdrvextra_cmd_parm->type_size = 0; - pdrvextra_cmd_parm->pbuf = (u8 *)padapter; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); -exit: - - return res; -} - -static void traffic_status_watchdog(struct rtw_adapter *padapter) -{ - u8 bEnterPS; - u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false; - u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false; - u8 bHigherBusyTxTraffic = false; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int BusyThreshold = 100; - struct rt_link_detect *ldi = &pmlmepriv->LinkDetectInfo; - - /* */ - /* Determine if our traffic is busy now */ - /* */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - if (rtl8723a_BT_coexist(padapter)) - BusyThreshold = 50; - else if (ldi->bBusyTraffic) - BusyThreshold = 75; - /* if we raise bBusyTraffic in last watchdog, using - lower threshold. */ - if (ldi->NumRxOkInPeriod > BusyThreshold || - ldi->NumTxOkInPeriod > BusyThreshold) { - bBusyTraffic = true; - - if (ldi->NumRxOkInPeriod > ldi->NumTxOkInPeriod) - bRxBusyTraffic = true; - else - bTxBusyTraffic = true; - } - - /* Higher Tx/Rx data. */ - if (ldi->NumRxOkInPeriod > 4000 || - ldi->NumTxOkInPeriod > 4000) { - bHigherBusyTraffic = true; - - if (ldi->NumRxOkInPeriod > ldi->NumTxOkInPeriod) - bHigherBusyRxTraffic = true; - else - bHigherBusyTxTraffic = true; - } - - if (!rtl8723a_BT_coexist(padapter) || - !rtl8723a_BT_using_antenna_1(padapter)) { - /* check traffic for powersaving. */ - if (((ldi->NumRxUnicastOkInPeriod + - ldi->NumTxOkInPeriod) > 8) || - ldi->NumRxUnicastOkInPeriod > 2) - bEnterPS = false; - else - bEnterPS = true; - - /* LeisurePS only work in infra mode. */ - if (bEnterPS) - LPS_Enter23a(padapter); - else - LPS_Leave23a(padapter); - } - } else - LPS_Leave23a(padapter); - - ldi->NumRxOkInPeriod = 0; - ldi->NumTxOkInPeriod = 0; - ldi->NumRxUnicastOkInPeriod = 0; - ldi->bBusyTraffic = bBusyTraffic; - ldi->bTxBusyTraffic = bTxBusyTraffic; - ldi->bRxBusyTraffic = bRxBusyTraffic; - ldi->bHigherBusyTraffic = bHigherBusyTraffic; - ldi->bHigherBusyRxTraffic = bHigherBusyRxTraffic; - ldi->bHigherBusyTxTraffic = bHigherBusyTxTraffic; -} - -static void dynamic_chk_wk_hdl(struct rtw_adapter *padapter, u8 *pbuf, int sz) -{ - struct mlme_priv *pmlmepriv; - - padapter = (struct rtw_adapter *)pbuf; - pmlmepriv = &padapter->mlmepriv; - -#ifdef CONFIG_8723AU_AP_MODE - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - expire_timeout_chk23a(padapter); -#endif - - rtl8723a_sreset_xmit_status_check(padapter); - - linked_status_chk23a(padapter); - traffic_status_watchdog(padapter); - - rtl8723a_HalDmWatchDog(padapter); - - /* */ - /* BT-Coexist */ - /* */ - rtl8723a_BT_do_coexist(padapter); -} - -static void lps_ctrl_wk_hdl(struct rtw_adapter *padapter, u8 lps_ctrl_type) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 mstatus; - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) - return; - - switch (lps_ctrl_type) { - case LPS_CTRL_SCAN: - rtl8723a_BT_wifiscan_notify(padapter, true); - if (!rtl8723a_BT_using_antenna_1(padapter)) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) - LPS_Leave23a(padapter); - } - break; - case LPS_CTRL_JOINBSS: - LPS_Leave23a(padapter); - break; - case LPS_CTRL_CONNECT: - mstatus = 1;/* connect */ - /* Reset LPS Setting */ - padapter->pwrctrlpriv.LpsIdleCount = 0; - rtl8723a_set_FwJoinBssReport_cmd(padapter, 1); - rtl8723a_BT_mediastatus_notify(padapter, mstatus); - break; - case LPS_CTRL_DISCONNECT: - mstatus = 0;/* disconnect */ - rtl8723a_BT_mediastatus_notify(padapter, mstatus); - if (!rtl8723a_BT_using_antenna_1(padapter)) - LPS_Leave23a(padapter); - rtl8723a_set_FwJoinBssReport_cmd(padapter, 0); - break; - case LPS_CTRL_SPECIAL_PACKET: - pwrpriv->DelayLPSLastTimeStamp = jiffies; - rtl8723a_BT_specialpacket_notify(padapter); - if (!rtl8723a_BT_using_antenna_1(padapter)) - LPS_Leave23a(padapter); - break; - case LPS_CTRL_LEAVE: - rtl8723a_BT_lps_leave(padapter); - if (!rtl8723a_BT_using_antenna_1(padapter)) - LPS_Leave23a(padapter); - break; - - default: - break; - } -} - -int rtw_lps_ctrl_wk_cmd23a(struct rtw_adapter *padapter, - u8 lps_ctrl_type, u8 enqueue) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - if (enqueue) { - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), - GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID; - pdrvextra_cmd_parm->type_size = lps_ctrl_type; - pdrvextra_cmd_parm->pbuf = NULL; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - } else - lps_ctrl_wk_hdl(padapter, lps_ctrl_type); -exit: - - return res; -} - -int rtw_ps_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *ppscmd; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ppscmd) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), - GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ppscmd); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID; - pdrvextra_cmd_parm->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ppscmd); -exit: - - return res; -} - -#ifdef CONFIG_8723AU_AP_MODE - -static void rtw_chk_hi_queue_hdl(struct rtw_adapter *padapter) -{ - int cnt = 0; - struct sta_info *psta_bmc; - struct sta_priv *pstapriv = &padapter->stapriv; - - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - if (!psta_bmc) - return; - - if (psta_bmc->sleepq_len == 0) { - bool val; - - val = rtl8723a_chk_hi_queue_empty(padapter); - - while (!val) { - msleep(100); - - cnt++; - - if (cnt > 10) - break; - - val = rtl8723a_chk_hi_queue_empty(padapter); - } - - if (cnt <= 10) { - pstapriv->tim_bitmap &= ~BIT(0); - pstapriv->sta_dz_bitmap &= ~BIT(0); - - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - } else /* re check again */ - rtw_chk_hi_queue_cmd23a(padapter); - } -} - -int rtw_chk_hi_queue_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), - GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID; - pdrvextra_cmd_parm->type_size = 0; - pdrvextra_cmd_parm->pbuf = NULL; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); -exit: - - return res; -} -#endif - -int rtw_c2h_wk_cmd23a(struct rtw_adapter *padapter, u8 *c2h_evt) -{ - struct cmd_obj *ph2c; - struct drvextra_cmd_parm *pdrvextra_cmd_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), - GFP_ATOMIC); - if (!pdrvextra_cmd_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - pdrvextra_cmd_parm->ec_id = C2H_WK_CID; - pdrvextra_cmd_parm->type_size = c2h_evt?16:0; - pdrvextra_cmd_parm->pbuf = c2h_evt; - - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, - GEN_CMD_CODE(_Set_Drv_Extra)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - -exit: - - return res; -} - -static int c2h_evt_hdl(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt) -{ - int ret = _FAIL; - u8 buf[16]; - - if (!c2h_evt) { - /* No c2h event in cmd_obj, read c2h event before handling*/ - if (c2h_evt_read23a(adapter, buf) == _SUCCESS) { - c2h_evt = (struct c2h_evt_hdr *)buf; - - ret = c2h_handler_8723a(adapter, c2h_evt); - } - } else - ret = c2h_handler_8723a(adapter, c2h_evt); - - return ret; -} - -static void rtw_irq_work(struct work_struct *work) -{ - struct evt_priv *evtpriv; - struct rtw_adapter *adapter; - - evtpriv = container_of(work, struct evt_priv, irq_wk); - adapter = container_of(evtpriv, struct rtw_adapter, evtpriv); - - c2h_evt_clear23a(adapter); -} - -void rtw_evt_work(struct work_struct *work) -{ - struct evt_work *ework; - struct rtw_adapter *adapter; - - ework = container_of(work, struct evt_work, work); - adapter = ework->adapter; - - c2h_evt_clear23a(adapter); - - if (!c2h_evt_exist(&ework->u.c2h_evt)) { - kfree(ework); - return; - } - - if (c2h_id_filter_ccx_8723a(ework->u.c2h_evt.id) == true) { - /* Handle CCX report here */ - c2h_handler_8723a(adapter, &ework->u.c2h_evt); - kfree(ework); - } else { - /* - * Enqueue into cmd_thread for others. - * ework will be turned into a c2h_evt and freed once it - * has been consumed. - */ - rtw_c2h_wk_cmd23a(adapter, (u8 *)&ework->u.c2h_evt); - } -} - -int rtw_drvextra_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct drvextra_cmd_parm *pdrvextra_cmd; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf; - - switch (pdrvextra_cmd->ec_id) { - case DYNAMIC_CHK_WK_CID: - dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, - pdrvextra_cmd->type_size); - break; - case POWER_SAVING_CTRL_WK_CID: - rtw_ps_processor23a(padapter); - break; - case LPS_CTRL_WK_CID: - lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size); - break; -#ifdef CONFIG_8723AU_AP_MODE - case CHECK_HIQ_WK_CID: - rtw_chk_hi_queue_hdl(padapter); - break; -#endif /* CONFIG_8723AU_AP_MODE */ - case C2H_WK_CID: - c2h_evt_hdl(padapter, - (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf); - break; - - default: - break; - } - - if (pdrvextra_cmd->pbuf && (pdrvextra_cmd->type_size > 0)) { - kfree(pdrvextra_cmd->pbuf); - /* - * No need to set pdrvextra_cmd->pbuf = NULL as we were - * operating on a copy of the original pcmd->parmbuf - * created in rtw_cmd_work(). - */ - } - - return H2C_SUCCESS; -} - -void rtw_survey_cmd_callback23a(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res == H2C_DROPPED) { - /* TODO: cancel timer and do timeout handler directly... */ - /* need to make timeout handlerOS independent */ - mod_timer(&pmlmepriv->scan_to_timer, - jiffies + msecs_to_jiffies(1)); - } else if (pcmd->res != H2C_SUCCESS) { - mod_timer(&pmlmepriv->scan_to_timer, - jiffies + msecs_to_jiffies(1)); - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "********Error: MgntActrtw_set_802_11_bssid23a_LIST_SCAN Fail ************\n"); - } - - /* free cmd */ - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_disassoc_cmd23a_callback(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res != H2C_SUCCESS) { - spin_lock_bh(&pmlmepriv->lock); - set_fwstate(pmlmepriv, _FW_LINKED); - spin_unlock_bh(&pmlmepriv->lock); - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "***Error: disconnect_cmd_callback Fail ***\n"); - return; - } - - /* free cmd */ - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_joinbss_cmd23a_callback(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res == H2C_DROPPED) { - /* TODO: cancel timer and do timeout handler directly... */ - /* need to make timeout handlerOS independent */ - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(1)); - } else if (pcmd->res != H2C_SUCCESS) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "********Error:rtw_select_and_join_from_scanned_queue Wait Sema Fail ************\n"); - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(1)); - } - - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct sta_info *psta; - struct wlan_network *pwlan; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue; - - if (pcmd->res != H2C_SUCCESS) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "********Error: rtw_createbss_cmd23a_callback Fail ************\n"); - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(1)); - } - - del_timer_sync(&pmlmepriv->assoc_timer); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - psta = rtw_get_stainfo23a(&padapter->stapriv, - pnetwork->MacAddress); - if (!psta) { - psta = rtw_alloc_stainfo23a(&padapter->stapriv, - pnetwork->MacAddress, - GFP_KERNEL); - if (!psta) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "Can't alloc sta_info when createbss_cmd_callback\n"); - goto createbss_cmd_fail; - } - } - - spin_lock_bh(&pmlmepriv->lock); - rtw_indicate_connect23a(padapter); - spin_unlock_bh(&pmlmepriv->lock); - } else { - pwlan = rtw_alloc_network(pmlmepriv, GFP_KERNEL); - spin_lock_bh(&scanned_queue->lock); - if (!pwlan) { - pwlan = rtw_get_oldest_wlan_network23a(scanned_queue); - if (!pwlan) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "Error: can't get pwlan in rtw23a_joinbss_event_cb\n"); - spin_unlock_bh(&scanned_queue->lock); - goto createbss_cmd_fail; - } - pwlan->last_scanned = jiffies; - } else { - list_add_tail(&pwlan->list, - &scanned_queue->queue); - } - - pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork); - memcpy(&pwlan->network, pnetwork, pnetwork->Length); - /* pwlan->fixed = true; */ - - /* list_add_tail(&pwlan->list, - &pmlmepriv->scanned_queue.queue); */ - - /* copy pdev_network information to - pmlmepriv->cur_network */ - memcpy(&tgt_network->network, pnetwork, - get_wlan_bssid_ex_sz(pnetwork)); - - /* reset DSConfig */ - - clr_fwstate(pmlmepriv, _FW_UNDER_LINKING); - - /* we will set _FW_LINKED when there is one more sat to - join us (rtw_stassoc_event_callback23a) */ - spin_unlock_bh(&scanned_queue->lock); - } - -createbss_cmd_fail: - - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_setstaKey_cmdrsp_callback23a(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct sta_priv *pstapriv; - struct set_stakey_rsp *psetstakey_rsp; - struct sta_info *psta; - - pstapriv = &padapter->stapriv; - psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp); - psta = rtw_get_stainfo23a(pstapriv, psetstakey_rsp->addr); - - if (!psta) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "ERROR: rtw_setstaKey_cmdrsp_callback23a => can't get sta_info\n"); - goto exit; - } - -exit: - - rtw_free_cmd_obj23a(pcmd); -} - -void rtw_setassocsta_cmdrsp_callback23a(struct rtw_adapter *padapter, - struct cmd_obj *pcmd) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct set_assocsta_parm *passocsta_parm; - struct set_assocsta_rsp *passocsta_rsp; - struct sta_info *psta; - - passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf); - passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp); - psta = rtw_get_stainfo23a(pstapriv, passocsta_parm->addr); - - if (psta == NULL) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "ERROR: setassocsta_cmdrsp_callbac => can't get sta_info\n"); - goto exit; - } - - psta->aid = psta->mac_id = passocsta_rsp->cam_id; - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && - check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - - set_fwstate(pmlmepriv, _FW_LINKED); - spin_unlock_bh(&pmlmepriv->lock); - -exit: - rtw_free_cmd_obj23a(pcmd); -} diff --git a/drivers/staging/rtl8723au/core/rtw_efuse.c b/drivers/staging/rtl8723au/core/rtw_efuse.c deleted file mode 100644 index 359ef4197e94..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_efuse.c +++ /dev/null @@ -1,538 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_EFUSE_C_ - -#include <osdep_service.h> -#include <drv_types.h> - -#include <rtw_efuse.h> -#include <rtl8723a_hal.h> -#include <usb_ops_linux.h> - -#define REG_EFUSE_CTRL 0x0030 -#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control */ - -#define VOLTAGE_V25 0x03 -#define LDOE25_SHIFT 28 - -/* - * When we want to enable write operation, we should change to - * pwr on state. When we stop write, we should switch to 500k mode - * and disable LDO 2.5V. - */ -static void Efuse_PowerSwitch(struct rtw_adapter *padapter, - u8 bWrite, u8 PwrState) -{ - u8 tempval; - u16 tmpV16; - - if (PwrState == true) { - rtl8723au_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON); - - /* - * 1.2V Power: From VDDON with Power - * Cut(0x0000h[15]), default valid - */ - tmpV16 = rtl8723au_read16(padapter, REG_SYS_ISO_CTRL); - if (!(tmpV16 & PWC_EV12V)) { - tmpV16 |= PWC_EV12V; - rtl8723au_write16(padapter, REG_SYS_ISO_CTRL, tmpV16); - } - /* Reset: 0x0000h[28], default valid */ - tmpV16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN); - if (!(tmpV16 & FEN_ELDR)) { - tmpV16 |= FEN_ELDR; - rtl8723au_write16(padapter, REG_SYS_FUNC_EN, tmpV16); - } - - /* - * Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) - * clock from ANA, default valid - */ - tmpV16 = rtl8723au_read16(padapter, REG_SYS_CLKR); - if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) { - tmpV16 |= (LOADER_CLK_EN | ANA8M); - rtl8723au_write16(padapter, REG_SYS_CLKR, tmpV16); - } - - if (bWrite == true) { - /* Enable LDO 2.5V before read/write action */ - tempval = rtl8723au_read8(padapter, EFUSE_TEST + 3); - tempval &= 0x0F; - tempval |= (VOLTAGE_V25 << 4); - rtl8723au_write8(padapter, EFUSE_TEST + 3, - tempval | 0x80); - } - } else { - rtl8723au_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF); - - if (bWrite == true) { - /* Disable LDO 2.5V after read/write action */ - tempval = rtl8723au_read8(padapter, EFUSE_TEST + 3); - rtl8723au_write8(padapter, EFUSE_TEST + 3, - tempval & 0x7F); - } - } -} - -u16 Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType) -{ - u16 ret = 0; - - if (efuseType == EFUSE_WIFI) - ret = rtl8723a_EfuseGetCurrentSize_WiFi(pAdapter); - else - ret = rtl8723a_EfuseGetCurrentSize_BT(pAdapter); - - return ret; -} - -/* Get current efuse area enabled word */ -u8 Efuse_CalculateWordCnts23a(u8 word_en) -{ - return hweight8((~word_en) & 0xf); -} - -/* - * Description: Execute E-Fuse read byte operation. - * - * Assumptions: 1. Boot from E-Fuse and successfully auto-load. - * 2. PASSIVE_LEVEL (USB interface) - */ -void ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf) -{ - u32 value32; - u8 readbyte; - u16 retry; - - /* Write Address */ - rtl8723au_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff)); - readbyte = rtl8723au_read8(Adapter, EFUSE_CTRL+2); - rtl8723au_write8(Adapter, EFUSE_CTRL+2, - ((_offset >> 8) & 0x03) | (readbyte & 0xfc)); - - /* Write bit 32 0 */ - readbyte = rtl8723au_read8(Adapter, EFUSE_CTRL+3); - rtl8723au_write8(Adapter, EFUSE_CTRL+3, readbyte & 0x7f); - - /* Check bit 32 read-ready */ - retry = 0; - value32 = rtl8723au_read32(Adapter, EFUSE_CTRL); - while (!((value32 >> 24) & 0x80) && retry < 10000) { - value32 = rtl8723au_read32(Adapter, EFUSE_CTRL); - retry++; - } - - /* - * Added suggested delay. This fixes the problem that - * Efuse read error in high temperature condition. - * Designer says that there shall be some delay after - * ready bit is set, or the result will always stay - * on last data we read. - */ - udelay(50); - value32 = rtl8723au_read32(Adapter, EFUSE_CTRL); - - *pbuf = (u8)(value32 & 0xff); -} - -void EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType, - u8 type, void *pOut) -{ - u8 *pu1Tmp; - u16 *pu2Tmp; - u8 *pMax_section; - - switch (type) { - case TYPE_EFUSE_MAX_SECTION: - pMax_section = pOut; - - if (efuseType == EFUSE_WIFI) - *pMax_section = EFUSE_MAX_SECTION_8723A; - else - *pMax_section = EFUSE_BT_MAX_SECTION; - break; - - case TYPE_EFUSE_REAL_CONTENT_LEN: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A; - else - *pu2Tmp = EFUSE_BT_REAL_CONTENT_LEN; - break; - - case TYPE_AVAILABLE_EFUSE_BYTES_BANK: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A - - EFUSE_OOB_PROTECT_BYTES); - else - *pu2Tmp = (EFUSE_BT_REAL_BANK_CONTENT_LEN - - EFUSE_PROTECT_BYTES_BANK); - break; - - case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A - - EFUSE_OOB_PROTECT_BYTES); - else - *pu2Tmp = (EFUSE_BT_REAL_CONTENT_LEN - - (EFUSE_PROTECT_BYTES_BANK * 3)); - break; - - case TYPE_EFUSE_MAP_LEN: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = EFUSE_MAP_LEN_8723A; - else - *pu2Tmp = EFUSE_BT_MAP_LEN; - break; - - case TYPE_EFUSE_PROTECT_BYTES_BANK: - pu1Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu1Tmp = EFUSE_OOB_PROTECT_BYTES; - else - *pu1Tmp = EFUSE_PROTECT_BYTES_BANK; - break; - - case TYPE_EFUSE_CONTENT_LEN_BANK: - pu2Tmp = pOut; - - if (efuseType == EFUSE_WIFI) - *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A; - else - *pu2Tmp = EFUSE_BT_REAL_BANK_CONTENT_LEN; - break; - - default: - pu1Tmp = pOut; - *pu1Tmp = 0; - break; - } -} - -/* Copy from WMAC for EFUSE read 1 byte. */ -u8 EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address) -{ - u8 data; - u8 Bytetemp = {0x00}; - u8 temp = {0x00}; - u32 k = 0; - u16 contentLen = 0; - - EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI, - TYPE_EFUSE_REAL_CONTENT_LEN, - (void *)&contentLen); - - if (Address < contentLen) { /* E-fuse 512Byte */ - /* Write E-fuse Register address bit0~7 */ - temp = Address & 0xFF; - rtl8723au_write8(Adapter, EFUSE_CTRL+1, temp); - Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+2); - /* Write E-fuse Register address bit8~9 */ - temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC); - rtl8723au_write8(Adapter, EFUSE_CTRL+2, temp); - - /* Write 0x30[31]= 0 */ - Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3); - temp = Bytetemp & 0x7F; - rtl8723au_write8(Adapter, EFUSE_CTRL+3, temp); - - /* Wait Write-ready (0x30[31]= 1) */ - Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3); - while (!(Bytetemp & 0x80)) { - Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3); - k++; - if (k == 1000) { - k = 0; - break; - } - } - data = rtl8723au_read8(Adapter, EFUSE_CTRL); - return data; - } - return 0xFF; -} - -/* Read one byte from real Efuse. */ -int efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data) -{ - u8 tmpidx = 0; - int bResult; - - /* -----------------e-fuse reg ctrl ---------------------------- */ - /* address */ - rtl8723au_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff)); - rtl8723au_write8(pAdapter, EFUSE_CTRL + 2, - ((u8)((addr >> 8) & 0x03)) | - (rtl8723au_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC)); - - rtl8723au_write8(pAdapter, EFUSE_CTRL + 3, 0x72); /* read cmd */ - - while (!(0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL + 3)) && - (tmpidx < 100)) - tmpidx++; - if (tmpidx < 100) { - *data = rtl8723au_read8(pAdapter, EFUSE_CTRL); - bResult = _SUCCESS; - } else { - *data = 0xff; - bResult = _FAIL; - } - return bResult; -} - -/* Write one byte to reald Efuse. */ -int efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data) -{ - u8 tmpidx = 0; - int bResult; - - /* return 0; */ - - /* -----------------e-fuse reg ctrl ------------------------- */ - /* address */ - rtl8723au_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff)); - rtl8723au_write8(pAdapter, EFUSE_CTRL + 2, - (rtl8723au_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) | - (u8)((addr >> 8) & 0x03)); - rtl8723au_write8(pAdapter, EFUSE_CTRL, data); /* data */ - - rtl8723au_write8(pAdapter, EFUSE_CTRL + 3, 0xF2); /* write cmd */ - - while ((0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL + 3)) && - (tmpidx < 100)) { - tmpidx++; - } - - if (tmpidx < 100) - bResult = _SUCCESS; - else - bResult = _FAIL; - - return bResult; -} - -/* Read allowed word in current efuse section data. */ -void efuse_WordEnableDataRead23a(u8 word_en, u8 *sourdata, u8 *targetdata) -{ - if (!(word_en&BIT(0))) { - targetdata[0] = sourdata[0]; - targetdata[1] = sourdata[1]; - } - if (!(word_en&BIT(1))) { - targetdata[2] = sourdata[2]; - targetdata[3] = sourdata[3]; - } - if (!(word_en&BIT(2))) { - targetdata[4] = sourdata[4]; - targetdata[5] = sourdata[5]; - } - if (!(word_en&BIT(3))) { - targetdata[6] = sourdata[6]; - targetdata[7] = sourdata[7]; - } -} - -static int efuse_read8(struct rtw_adapter *padapter, u16 address, u8 *value) -{ - return efuse_OneByteRead23a(padapter, address, value); -} - -static int efuse_write8(struct rtw_adapter *padapter, u16 address, u8 *value) -{ - return efuse_OneByteWrite23a(padapter, address, *value); -} - -/* read/write raw efuse data */ -int rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bWrite, u16 start_addr, - u16 cnts, u8 *data) -{ - int i = 0; - u16 real_content_len = 0, max_available_size = 0; - int res = _FAIL; - int (*rw8)(struct rtw_adapter *, u16, u8*); - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, - TYPE_EFUSE_REAL_CONTENT_LEN, - (void *)&real_content_len); - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, - TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, - (void *)&max_available_size); - - if (start_addr > real_content_len) - return _FAIL; - - if (true == bWrite) { - if ((start_addr + cnts) > max_available_size) - return _FAIL; - rw8 = &efuse_write8; - } else - rw8 = &efuse_read8; - - Efuse_PowerSwitch(padapter, bWrite, true); - - /* e-fuse one byte read/write */ - for (i = 0; i < cnts; i++) { - if (start_addr >= real_content_len) { - res = _FAIL; - break; - } - - res = rw8(padapter, start_addr++, data++); - if (res == _FAIL) - break; - } - - Efuse_PowerSwitch(padapter, bWrite, false); - - return res; -} - -u16 efuse_GetMaxSize23a(struct rtw_adapter *padapter) -{ - u16 max_size; - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, - TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, - (void *)&max_size); - return max_size; -} - -int rtw_efuse_map_read23a(struct rtw_adapter *padapter, - u16 addr, u16 cnts, u8 *data) -{ - u16 mapLen = 0; - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, - TYPE_EFUSE_MAP_LEN, (void *)&mapLen); - - if ((addr + cnts) > mapLen) - return _FAIL; - - Efuse_PowerSwitch(padapter, false, true); - - rtl8723a_readefuse(padapter, EFUSE_WIFI, addr, cnts, data); - - Efuse_PowerSwitch(padapter, false, false); - - return _SUCCESS; -} - -int rtw_BT_efuse_map_read23a(struct rtw_adapter *padapter, - u16 addr, u16 cnts, u8 *data) -{ - u16 mapLen = 0; - - EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT, - TYPE_EFUSE_MAP_LEN, (void *)&mapLen); - - if ((addr + cnts) > mapLen) - return _FAIL; - - Efuse_PowerSwitch(padapter, false, true); - - rtl8723a_readefuse(padapter, EFUSE_BT, addr, cnts, data); - - Efuse_PowerSwitch(padapter, false, false); - - return _SUCCESS; -} - -/* Read All Efuse content */ -static void Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, - u8 *Efuse) -{ - u16 mapLen = 0; - - Efuse_PowerSwitch(pAdapter, false, true); - - EFUSE_GetEfuseDefinition23a(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, - (void *)&mapLen); - - rtl8723a_readefuse(pAdapter, efuseType, 0, mapLen, Efuse); - - Efuse_PowerSwitch(pAdapter, false, false); -} - -/* - * Functions: efuse_ShadowRead1Byte - * efuse_ShadowRead2Byte - * efuse_ShadowRead4Byte - * - * Read from efuse init map by one/two/four bytes - */ -static void efuse_ShadowRead1Byte(struct rtw_adapter *pAdapter, u16 Offset, - u8 *Value) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); - - *Value = pEEPROM->efuse_eeprom_data[Offset]; -} - -static void efuse_ShadowRead2Byte(struct rtw_adapter *pAdapter, u16 Offset, - u16 *Value) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); - - *Value = pEEPROM->efuse_eeprom_data[Offset]; - *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8; -} - -static void efuse_ShadowRead4Byte(struct rtw_adapter *pAdapter, u16 Offset, - u32 *Value) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); - - *Value = pEEPROM->efuse_eeprom_data[Offset]; - *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8; - *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16; - *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24; -} - -/* Transfer current EFUSE content to shadow init and modify map. */ -void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType) -{ - struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); - u16 mapLen = 0; - - EFUSE_GetEfuseDefinition23a(pAdapter, efuseType, - TYPE_EFUSE_MAP_LEN, (void *)&mapLen); - - if (pEEPROM->bautoload_fail_flag == true) - memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen); - else - Efuse_ReadAllMap(pAdapter, efuseType, - pEEPROM->efuse_eeprom_data); -} - -/* Read from efuse init map */ -void EFUSE_ShadowRead23a(struct rtw_adapter *pAdapter, u8 Type, - u16 Offset, u32 *Value) -{ - if (Type == 1) - efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value); - else if (Type == 2) - efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value); - else if (Type == 4) - efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value); -} diff --git a/drivers/staging/rtl8723au/core/rtw_ieee80211.c b/drivers/staging/rtl8723au/core/rtw_ieee80211.c deleted file mode 100644 index 07a6490a83d6..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_ieee80211.c +++ /dev/null @@ -1,855 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _IEEE80211_C - -#include <drv_types.h> -#include <linux/ieee80211.h> -#include <ieee80211.h> -#include <wifi.h> -#include <osdep_service.h> -#include <wlan_bssdef.h> - -u8 RTW_WPA_OUI23A_TYPE[] = { 0x00, 0x50, 0xf2, 1 }; -u16 RTW_WPA_VERSION23A = 1; -u8 WPA_AUTH_KEY_MGMT_NONE23A[] = { 0x00, 0x50, 0xf2, 0 }; -u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X23A[] = { 0x00, 0x50, 0xf2, 1 }; -u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[] = { 0x00, 0x50, 0xf2, 2 }; -u8 WPA_CIPHER_SUITE_NONE23A[] = { 0x00, 0x50, 0xf2, 0 }; -u8 WPA_CIPHER_SUITE_WEP4023A[] = { 0x00, 0x50, 0xf2, 1 }; -u8 WPA_CIPHER_SUITE_TKIP23A[] = { 0x00, 0x50, 0xf2, 2 }; -u8 WPA_CIPHER_SUITE_WRAP23A[] = { 0x00, 0x50, 0xf2, 3 }; -u8 WPA_CIPHER_SUITE_CCMP23A[] = { 0x00, 0x50, 0xf2, 4 }; -u8 WPA_CIPHER_SUITE_WEP10423A[] = { 0x00, 0x50, 0xf2, 5 }; - -u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X23A[] = { 0x00, 0x0f, 0xac, 1 }; -u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[] = { 0x00, 0x0f, 0xac, 2 }; -u8 RSN_CIPHER_SUITE_NONE23A[] = { 0x00, 0x0f, 0xac, 0 }; -u8 RSN_CIPHER_SUITE_WEP4023A[] = { 0x00, 0x0f, 0xac, 1 }; -u8 RSN_CIPHER_SUITE_TKIP23A[] = { 0x00, 0x0f, 0xac, 2 }; -u8 RSN_CIPHER_SUITE_WRAP23A[] = { 0x00, 0x0f, 0xac, 3 }; -u8 RSN_CIPHER_SUITE_CCMP23A[] = { 0x00, 0x0f, 0xac, 4 }; -u8 RSN_CIPHER_SUITE_WEP10423A[] = { 0x00, 0x0f, 0xac, 5 }; -/* */ -/* for adhoc-master to generate ie and provide supported-rate to fw */ -/* */ - -static u8 WIFI_CCKRATES[] = { - IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK -}; - -static u8 WIFI_OFDMRATES[] = { - IEEE80211_OFDM_RATE_6MB, - IEEE80211_OFDM_RATE_9MB, - IEEE80211_OFDM_RATE_12MB, - IEEE80211_OFDM_RATE_18MB, - IEEE80211_OFDM_RATE_24MB, - IEEE80211_OFDM_RATE_36MB, - IEEE80211_OFDM_RATE_48MB, - IEEE80211_OFDM_RATE_54MB -}; - -int rtw_get_bit_value_from_ieee_value23a(u8 val) -{ - unsigned char dot11_rate_table[]= - {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 0}; - - int i = 0; - - while (dot11_rate_table[i] != 0) { - if (dot11_rate_table[i] == val) - return BIT(i); - i++; - } - return 0; -} - -static bool rtw_is_cckrates_included(u8 *rate) -{ - u32 i = 0; - - while (rate[i]) { - if ((rate[i] & 0x7f) == 2 || (rate[i] & 0x7f) == 4 || - (rate[i] & 0x7f) == 11 || (rate[i] & 0x7f) == 22) - return true; - i++; - } - - return false; -} - -static bool rtw_is_cckratesonly_included(u8 *rate) -{ - u32 i = 0; - - while (rate[i]) { - if ((rate[i] & 0x7f) != 2 && (rate[i] & 0x7f) != 4 && - (rate[i] & 0x7f) != 11 && (rate[i] & 0x7f) != 22) - return false; - - i++; - } - - return true; -} - -int rtw_check_network_type23a(unsigned char *rate, int ratelen, int channel) -{ - if (channel > 14) { - if (rtw_is_cckrates_included(rate)) - return WIRELESS_INVALID; - else - return WIRELESS_11A; - } else { /* could be pure B, pure G, or B/G */ - if (rtw_is_cckratesonly_included(rate)) - return WIRELESS_11B; - else if (rtw_is_cckrates_included(rate)) - return WIRELESS_11BG; - else - return WIRELESS_11G; - } -} - -/* rtw_set_ie23a will update frame length */ -u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, const u8 *source, uint *frlen) -{ - - *pbuf = (u8)index; - - *(pbuf + 1) = (u8)len; - - if (len > 0) - memcpy((void *)(pbuf + 2), (void *)source, len); - - *frlen = *frlen + (len + 2); - - return pbuf + len + 2; -} - -inline u8 *rtw_set_ie23a_ch_switch (u8 *buf, u32 *buf_len, u8 ch_switch_mode, - u8 new_ch, u8 ch_switch_cnt) -{ - u8 ie_data[3]; - - ie_data[0] = ch_switch_mode; - ie_data[1] = new_ch; - ie_data[2] = ch_switch_cnt; - return rtw_set_ie23a(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len); -} - -inline u8 hal_ch_offset_to_secondary_ch_offset23a(u8 ch_offset) -{ - if (ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - return IEEE80211_HT_PARAM_CHA_SEC_BELOW; - else if (ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - return IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - - return IEEE80211_HT_PARAM_CHA_SEC_NONE; -} - -inline u8 *rtw_set_ie23a_secondary_ch_offset(u8 *buf, u32 *buf_len, - u8 secondary_ch_offset) -{ - return rtw_set_ie23a(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET, - 1, &secondary_ch_offset, buf_len); -} - -/*---------------------------------------------------------------------------- -index: the information element id index, limit is the limit for search ------------------------------------------------------------------------------*/ -u8 *rtw_get_ie23a(u8 *pbuf, int index, int *len, int limit) -{ - int tmp, i; - u8 *p; - - if (limit < 1) { - - return NULL; - } - - p = pbuf; - i = 0; - *len = 0; - while (1) { - if (*p == index) { - *len = *(p + 1); - return p; - } else { - tmp = *(p + 1); - p += (tmp + 2); - i += (tmp + 2); - } - if (i >= limit) - break; - } - - return NULL; -} - -/** - * rtw_get_ie23a_ex - Search specific IE from a series of IEs - * @in_ie: Address of IEs to search - * @in_len: Length limit from in_ie - * @eid: Element ID to match - * @oui: OUI to match - * @oui_len: OUI length - * @ie: If not NULL and the specific IE is found, the IE will be copied - * to the buf starting from the specific IE - * @ielen: If not NULL and the specific IE is found, will set to the length - * of the entire IE - * - * Returns: The address of the specific IE found, or NULL - */ -u8 *rtw_get_ie23a_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, - u8 *ie, uint *ielen) -{ - uint cnt; - u8 *target_ie = NULL; - - if (ielen) - *ielen = 0; - - if (!in_ie || in_len <= 0) - return target_ie; - - cnt = 0; - - while (cnt < in_len) { - if (eid == in_ie[cnt] && - (!oui || !memcmp(&in_ie[cnt+2], oui, oui_len))) { - target_ie = &in_ie[cnt]; - - if (ie) - memcpy(ie, &in_ie[cnt], in_ie[cnt+1]+2); - - if (ielen) - *ielen = in_ie[cnt+1]+2; - break; - } else { - cnt += in_ie[cnt + 1] + 2; /* goto next */ - } - } - - return target_ie; -} - -/** - * rtw_ies_remove_ie23a - Find matching IEs and remove - * @ies: Address of IEs to search - * @ies_len: Pointer of length of ies, will update to new length - * @offset: The offset to start search - * @eid: Element ID to match - * @oui: OUI to match - * @oui_len: OUI length - * - * Returns: _SUCCESS: ies is updated, _FAIL: not updated - */ -int rtw_ies_remove_ie23a(u8 *ies, uint *ies_len, uint offset, u8 eid, - u8 *oui, u8 oui_len) -{ - int ret = _FAIL; - u8 *target_ie; - u32 target_ielen; - u8 *start; - uint search_len; - - if (!ies || !ies_len || *ies_len <= offset) - goto exit; - - start = ies + offset; - search_len = *ies_len - offset; - - while (1) { - target_ie = rtw_get_ie23a_ex(start, search_len, eid, oui, oui_len, - NULL, &target_ielen); - if (target_ie && target_ielen) { - u8 buf[MAX_IE_SZ] = {0}; - u8 *remain_ies = target_ie + target_ielen; - uint remain_len = search_len - (remain_ies - start); - - memcpy(buf, remain_ies, remain_len); - memcpy(target_ie, buf, remain_len); - *ies_len = *ies_len - target_ielen; - ret = _SUCCESS; - - start = target_ie; - search_len = remain_len; - } else { - break; - } - } -exit: - return ret; -} - -void rtw_set_supported_rate23a(u8 *SupportedRates, uint mode) -{ - - - memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); - - switch (mode) { - case WIRELESS_11B: - memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); - break; - - case WIRELESS_11G: - case WIRELESS_11A: - case WIRELESS_11_5N: - case WIRELESS_11A_5N:/* Todo: no basic rate for ofdm ? */ - memcpy(SupportedRates, WIFI_OFDMRATES, - IEEE80211_NUM_OFDM_RATESLEN); - break; - - case WIRELESS_11BG: - case WIRELESS_11G_24N: - case WIRELESS_11_24N: - case WIRELESS_11BG_24N: - memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); - memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, - IEEE80211_NUM_OFDM_RATESLEN); - break; - } - -} - -uint rtw_get_rateset_len23a(u8 *rateset) -{ - uint i = 0; - - while(1) { - if (rateset[i] == 0) - break; - - if (i > 12) - break; - - i++; - } - - return i; -} - -int rtw_generate_ie23a(struct registry_priv *pregistrypriv) -{ - u8 wireless_mode; - int sz = 0, rateLen; - struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; - u8 *ie = pdev_network->IEs; - u16 cap; - - pdev_network->tsf = 0; - - cap = WLAN_CAPABILITY_IBSS; - - if (pregistrypriv->preamble == PREAMBLE_SHORT) - cap |= WLAN_CAPABILITY_SHORT_PREAMBLE; - - if (pdev_network->Privacy) - cap |= WLAN_CAPABILITY_PRIVACY; - - pdev_network->capability = cap; - - /* SSID */ - ie = rtw_set_ie23a(ie, WLAN_EID_SSID, pdev_network->Ssid.ssid_len, - pdev_network->Ssid.ssid, &sz); - - /* supported rates */ - if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) { - if (pdev_network->DSConfig > 14) - wireless_mode = WIRELESS_11A_5N; - else - wireless_mode = WIRELESS_11BG_24N; - } else { - wireless_mode = pregistrypriv->wireless_mode; - } - - rtw_set_supported_rate23a(pdev_network->SupportedRates, wireless_mode) ; - - rateLen = rtw_get_rateset_len23a(pdev_network->SupportedRates); - - if (rateLen > 8) { - ie = rtw_set_ie23a(ie, WLAN_EID_SUPP_RATES, 8, - pdev_network->SupportedRates, &sz); - /* ie = rtw_set_ie23a(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */ - } else { - ie = rtw_set_ie23a(ie, WLAN_EID_SUPP_RATES, rateLen, - pdev_network->SupportedRates, &sz); - } - - /* DS parameter set */ - ie = rtw_set_ie23a(ie, WLAN_EID_DS_PARAMS, 1, - (u8 *)&pdev_network->DSConfig, &sz); - - /* IBSS Parameter Set */ - - ie = rtw_set_ie23a(ie, WLAN_EID_IBSS_PARAMS, 2, - (u8 *)&pdev_network->ATIMWindow, &sz); - - if (rateLen > 8) { - ie = rtw_set_ie23a(ie, WLAN_EID_EXT_SUPP_RATES, (rateLen - 8), - (pdev_network->SupportedRates + 8), &sz); - } - - - - /* return _SUCCESS; */ - - return sz; -} - -static int rtw_get_wpa_cipher_suite(const u8 *s) -{ - if (!memcmp(s, WPA_CIPHER_SUITE_NONE23A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_NONE; - if (!memcmp(s, WPA_CIPHER_SUITE_WEP4023A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_WEP40; - if (!memcmp(s, WPA_CIPHER_SUITE_TKIP23A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_TKIP; - if (!memcmp(s, WPA_CIPHER_SUITE_CCMP23A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_CCMP; - if (!memcmp(s, WPA_CIPHER_SUITE_WEP10423A, WPA_SELECTOR_LEN)) - return WPA_CIPHER_WEP104; - - return 0; -} - -static int rtw_get_wpa2_cipher_suite(const u8 *s) -{ - if (!memcmp(s, RSN_CIPHER_SUITE_NONE23A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_NONE; - if (!memcmp(s, RSN_CIPHER_SUITE_WEP4023A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_WEP40; - if (!memcmp(s, RSN_CIPHER_SUITE_TKIP23A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_TKIP; - if (!memcmp(s, RSN_CIPHER_SUITE_CCMP23A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_CCMP; - if (!memcmp(s, RSN_CIPHER_SUITE_WEP10423A, RSN_SELECTOR_LEN)) - return WPA_CIPHER_WEP104; - - return 0; -} - -int rtw_parse_wpa_ie23a(const u8 *wpa_ie, int wpa_ie_len, int *group_cipher, - int *pairwise_cipher, int *is_8021x) -{ - int i, ret = _SUCCESS; - int left, count; - const u8 *pos; - - if (wpa_ie_len <= 0) { - /* No WPA IE - fail silently */ - return _FAIL; - } - - if (wpa_ie[1] != (u8)(wpa_ie_len - 2)) - return _FAIL; - - pos = wpa_ie; - - pos += 8; - left = wpa_ie_len - 8; - - /* group_cipher */ - if (left >= WPA_SELECTOR_LEN) { - - *group_cipher = rtw_get_wpa_cipher_suite(pos); - - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } else if (left > 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie length mismatch, %u too much\n", - __func__, left); - - return _FAIL; - } - - /* pairwise_cipher */ - if (left >= 2) { - /* count = le16_to_cpu(*(u16*)pos); */ - count = get_unaligned_le16(pos); - pos += 2; - left -= 2; - - if (count == 0 || left < count * WPA_SELECTOR_LEN) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie count botch (pairwise), count %u left %u\n", - __func__, count, left); - return _FAIL; - } - - for (i = 0; i < count; i++) { - *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos); - - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } - } else if (left == 1) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie too short (for key mgmt)\n", __func__); - return _FAIL; - } - - if (is_8021x) { - if (left >= 6) { - pos += 2; - if (!memcmp(pos, RTW_WPA_OUI23A_TYPE, 4)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s : there has 802.1x auth\n", - __func__); - *is_8021x = 1; - } - } - } - - return ret; -} - -int rtw_parse_wpa2_ie23a(const u8 *rsn_ie, int rsn_ie_len, int *group_cipher, - int *pairwise_cipher, int *is_8021x) -{ - int i, ret = _SUCCESS; - int left, count; - const u8 *pos; - u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01}; - - if (rsn_ie_len <= 0) { - /* No RSN IE - fail silently */ - return _FAIL; - } - - if (*rsn_ie != WLAN_EID_RSN || *(rsn_ie+1) != (u8)(rsn_ie_len - 2)) { - return _FAIL; - } - - pos = rsn_ie; - pos += 4; - left = rsn_ie_len - 4; - - /* group_cipher */ - if (left >= RSN_SELECTOR_LEN) { - *group_cipher = rtw_get_wpa2_cipher_suite(pos); - - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } else if (left > 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie length mismatch, %u too much\n", - __func__, left); - return _FAIL; - } - - /* pairwise_cipher */ - if (left >= 2) { - /* count = le16_to_cpu(*(u16*)pos); */ - count = get_unaligned_le16(pos); - pos += 2; - left -= 2; - - if (count == 0 || left < count * RSN_SELECTOR_LEN) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie count botch (pairwise), count %u left %u\n", - __func__, count, left); - return _FAIL; - } - - for (i = 0; i < count; i++) { - *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos); - - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } - } else if (left == 1) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s: ie too short (for key mgmt)\n", __func__); - - return _FAIL; - } - - if (is_8021x) { - if (left >= 6) { - pos += 2; - if (!memcmp(pos, SUITE_1X, 4)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s (): there has 802.1x auth\n", - __func__); - *is_8021x = 1; - } - } - } - - return ret; -} - -/** - * rtw_get_wps_attr23a - Search a specific WPS attribute from a given WPS IE - * @wps_ie: Address of WPS IE to search - * @wps_ielen: Length limit from wps_ie - * @target_attr_id: The attribute ID of WPS attribute to search - * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute - * will be copied to the buf starting from buf_attr - * @len_attr: If not NULL and the WPS attribute is found, will set to the - * length of the entire WPS attribute - * - * Returns: the address of the specific WPS attribute found, or NULL - */ -const u8 *rtw_get_wps_attr23a(const u8 *wps_ie, uint wps_ielen, - u16 target_attr_id, u8 *buf_attr, u32 *len_attr) -{ - const u8 *attr_ptr = NULL; - const u8 *target_attr_ptr = NULL; - u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04}; - - if (len_attr) - *len_attr = 0; - - if (wps_ie[0] != WLAN_EID_VENDOR_SPECIFIC || - memcmp(wps_ie + 2, wps_oui, 4)) { - return attr_ptr; - } - - /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */ - attr_ptr = wps_ie + 6; /* goto first attr */ - - while (attr_ptr - wps_ie < wps_ielen) { - /* 4 = 2(Attribute ID) + 2(Length) */ - u16 attr_id = get_unaligned_be16(attr_ptr); - u16 attr_data_len = get_unaligned_be16(attr_ptr + 2); - u16 attr_len = attr_data_len + 4; - - /* DBG_8723A("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); */ - if (attr_id == target_attr_id) { - target_attr_ptr = attr_ptr; - - if (buf_attr) - memcpy(buf_attr, attr_ptr, attr_len); - - if (len_attr) - *len_attr = attr_len; - - break; - } else { - attr_ptr += attr_len; /* goto next */ - } - } - - return target_attr_ptr; -} - -/** - * rtw_get_wps_attr_content23a - Search a specific WPS attribute content - * from a given WPS IE - * @wps_ie: Address of WPS IE to search - * @wps_ielen: Length limit from wps_ie - * @target_attr_id: The attribute ID of WPS attribute to search - * @buf_content: If not NULL and the WPS attribute is found, WPS attribute - * content will be copied to the buf starting from buf_content - * @len_content: If not NULL and the WPS attribute is found, will set to the - * length of the WPS attribute content - * - * Returns: the address of the specific WPS attribute content found, or NULL - */ -const u8 *rtw_get_wps_attr_content23a(const u8 *wps_ie, uint wps_ielen, - u16 target_attr_id, u8 *buf_content) -{ - const u8 *attr_ptr; - u32 attr_len; - - attr_ptr = rtw_get_wps_attr23a(wps_ie, wps_ielen, target_attr_id, - NULL, &attr_len); - - if (attr_ptr && attr_len) { - if (buf_content) - memcpy(buf_content, attr_ptr + 4, attr_len - 4); - - return attr_ptr + 4; - } - - return NULL; -} - -static int rtw_get_cipher_info(struct wlan_network *pnetwork) -{ - const u8 *pbuf; - int group_cipher = 0, pairwise_cipher = 0, is8021x = 0; - int ret = _FAIL; - int r, plen; - char *pie; - - pie = pnetwork->network.IEs; - plen = pnetwork->network.IELength; - - pbuf = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, pie, plen); - - if (pbuf && pbuf[1] > 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw_get_cipher_info: wpa_ielen: %d\n", pbuf[1]); - r = rtw_parse_wpa_ie23a(pbuf, pbuf[1] + 2, &group_cipher, - &pairwise_cipher, &is8021x); - if (r == _SUCCESS) { - pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher; - pnetwork->BcnInfo.group_cipher = group_cipher; - pnetwork->BcnInfo.is_8021x = is8021x; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s: pnetwork->pairwise_cipher: %d, is_8021x is %d\n", - __func__, pnetwork->BcnInfo.pairwise_cipher, - pnetwork->BcnInfo.is_8021x); - ret = _SUCCESS; - } - } else { - pbuf = cfg80211_find_ie(WLAN_EID_RSN, pie, plen); - - if (pbuf && pbuf[1] > 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "get RSN IE\n"); - r = rtw_parse_wpa2_ie23a(pbuf, pbuf[1] + 2, - &group_cipher, &pairwise_cipher, - &is8021x); - if (r == _SUCCESS) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "get RSN IE OK!!!\n"); - pnetwork->BcnInfo.pairwise_cipher = - pairwise_cipher; - pnetwork->BcnInfo.group_cipher = group_cipher; - pnetwork->BcnInfo.is_8021x = is8021x; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s: pnetwork->pairwise_cipher: %d,pnetwork->group_cipher is %d, is_8021x is %d\n", - __func__, - pnetwork->BcnInfo.pairwise_cipher, - pnetwork->BcnInfo.group_cipher, - pnetwork->BcnInfo.is_8021x); - ret = _SUCCESS; - } - } - } - - return ret; -} - -void rtw_get_bcn_info23a(struct wlan_network *pnetwork) -{ - u8 bencrypt = 0; - int pie_len; - u8 *pie; - const u8 *p; - - if (pnetwork->network.capability & WLAN_CAPABILITY_PRIVACY) { - bencrypt = 1; - pnetwork->network.Privacy = 1; - } else - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s: ssid =%s\n", __func__, pnetwork->network.Ssid.ssid); - - pie = pnetwork->network.IEs; - pie_len = pnetwork->network.IELength; - - p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len); - if (p && p[1]) { - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2; - } else if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - pie, pie_len)) { - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA; - } else { - if (bencrypt) - pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP; - } - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s: pnetwork->encryp_protocol is %x\n", __func__, - pnetwork->BcnInfo.encryp_protocol); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s: pnetwork->encryp_protocol is %x\n", __func__, - pnetwork->BcnInfo.encryp_protocol); - rtw_get_cipher_info(pnetwork); - - /* get bwmode and ch_offset */ -} - -/* show MCS rate, unit: 100Kbps */ -u16 rtw_mcs_rate23a(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, - struct ieee80211_mcs_info *mcs) -{ - u16 max_rate = 0; - - if (rf_type == RF_1T1R) { - if (mcs->rx_mask[0] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350): - ((short_GI_20)?722:650); - else if (mcs->rx_mask[0] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215): - ((short_GI_20)?650:585); - else if (mcs->rx_mask[0] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080): - ((short_GI_20)?578:520); - else if (mcs->rx_mask[0] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI_40)?900:810): - ((short_GI_20)?433:390); - else if (mcs->rx_mask[0] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI_40)?600:540): - ((short_GI_20)?289:260); - else if (mcs->rx_mask[0] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI_40)?450:405): - ((short_GI_20)?217:195); - else if (mcs->rx_mask[0] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI_40)?300:270): - ((short_GI_20)?144:130); - else if (mcs->rx_mask[0] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI_40)?150:135): - ((short_GI_20)?72:65); - } else { - if (mcs->rx_mask[1]) { - if (mcs->rx_mask[1] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI_40)?3000:2700):((short_GI_20)?1444:1300); - else if (mcs->rx_mask[1] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI_40)?2700:2430):((short_GI_20)?1300:1170); - else if (mcs->rx_mask[1] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI_40)?2400:2160):((short_GI_20)?1156:1040); - else if (mcs->rx_mask[1] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1800:1620):((short_GI_20)?867:780); - else if (mcs->rx_mask[1] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520); - else if (mcs->rx_mask[1] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390); - else if (mcs->rx_mask[1] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260); - else if (mcs->rx_mask[1] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130); - } else { - if (mcs->rx_mask[0] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350):((short_GI_20)?722:650); - else if (mcs->rx_mask[0] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215):((short_GI_20)?650:585); - else if (mcs->rx_mask[0] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520); - else if (mcs->rx_mask[0] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390); - else if (mcs->rx_mask[0] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260); - else if (mcs->rx_mask[0] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI_40)?450:405):((short_GI_20)?217:195); - else if (mcs->rx_mask[0] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130); - else if (mcs->rx_mask[0] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI_40)?150:135):((short_GI_20)?72:65); - } - } - return max_rate; -} diff --git a/drivers/staging/rtl8723au/core/rtw_mlme.c b/drivers/staging/rtl8723au/core/rtw_mlme.c deleted file mode 100644 index a786fc4bdb53..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_mlme.c +++ /dev/null @@ -1,2314 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_MLME_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <recv_osdep.h> -#include <xmit_osdep.h> -#include <hal_intf.h> -#include <mlme_osdep.h> -#include <sta_info.h> -#include <linux/ieee80211.h> -#include <wifi.h> -#include <wlan_bssdef.h> -#include <rtw_sreset.h> - -static struct wlan_network * -rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv); -static int rtw_do_join(struct rtw_adapter *padapter); - -static void rtw_init_mlme_timer(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - setup_timer(&pmlmepriv->assoc_timer, rtw23a_join_to_handler, - (unsigned long)padapter); - - setup_timer(&pmlmepriv->scan_to_timer, rtw_scan_timeout_handler23a, - (unsigned long)padapter); - - setup_timer(&pmlmepriv->dynamic_chk_timer, - rtw_dynamic_check_timer_handler, (unsigned long)padapter); - - setup_timer(&pmlmepriv->set_scan_deny_timer, - rtw_set_scan_deny_timer_hdl, (unsigned long)padapter); -} - -int rtw_init_mlme_priv23a(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pmlmepriv->nic_hdl = padapter; - - pmlmepriv->fw_state = 0; - pmlmepriv->cur_network.network.ifmode = NL80211_IFTYPE_UNSPECIFIED; - /* 1: active, 0: pasive. Maybe someday we should rename this - varable to "active_mode" (Jeff) */ - pmlmepriv->scan_mode = SCAN_ACTIVE; - - spin_lock_init(&pmlmepriv->lock); - _rtw_init_queue23a(&pmlmepriv->scanned_queue); - - memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct cfg80211_ssid)); - - rtw_clear_scan_deny(padapter); - - rtw_init_mlme_timer(padapter); - return _SUCCESS; -} - -#ifdef CONFIG_8723AU_AP_MODE -static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen) -{ - if (*ppie) { - kfree(*ppie); - *plen = 0; - *ppie = NULL; - } -} -#endif - -void rtw23a_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv) -{ -#ifdef CONFIG_8723AU_AP_MODE - kfree(pmlmepriv->assoc_req); - kfree(pmlmepriv->assoc_rsp); - rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, - &pmlmepriv->wps_probe_req_ie_len); -#endif -} - -void rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv) -{ - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_free_mlme_priv23a\n"); - - rtw23a_free_mlme_priv_ie_data(pmlmepriv); -} - -struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv, gfp_t gfp) -{ - struct wlan_network *pnetwork; - - pnetwork = kzalloc(sizeof(struct wlan_network), gfp); - if (pnetwork) { - INIT_LIST_HEAD(&pnetwork->list); - pnetwork->network_type = 0; - pnetwork->fixed = false; - pnetwork->last_scanned = jiffies; - pnetwork->join_res = 0; - } - - return pnetwork; -} - -static void _rtw_free_network23a(struct mlme_priv *pmlmepriv, - struct wlan_network *pnetwork) -{ - if (!pnetwork) - return; - - if (pnetwork->fixed == true) - return; - - list_del_init(&pnetwork->list); - - kfree(pnetwork); -} - -/* - return the wlan_network with the matching addr - - Shall be called under atomic context... to avoid possible racing condition... -*/ -struct wlan_network * -rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr) -{ - struct list_head *phead, *plist; - struct wlan_network *pnetwork = NULL; - - if (is_zero_ether_addr(addr)) { - pnetwork = NULL; - goto exit; - } - - /* spin_lock_bh(&scanned_queue->lock); */ - - phead = get_list_head(scanned_queue); - plist = phead->next; - - while (plist != phead) { - pnetwork = container_of(plist, struct wlan_network, list); - - if (ether_addr_equal(addr, pnetwork->network.MacAddress)) - break; - - plist = plist->next; - } - - if (plist == phead) - pnetwork = NULL; - - /* spin_unlock_bh(&scanned_queue->lock); */ - -exit: - - return pnetwork; -} - -void rtw_free_network_queue23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - struct wlan_network *pnetwork, *ptmp; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue; - - spin_lock_bh(&scanned_queue->lock); - phead = get_list_head(scanned_queue); - list_for_each_entry_safe(pnetwork, ptmp, phead, list) - _rtw_free_network23a(pmlmepriv, pnetwork); - spin_unlock_bh(&scanned_queue->lock); -} - -int rtw_if_up23a(struct rtw_adapter *padapter) -{ - int res; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved || - !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw_if_up23a:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", - padapter->bDriverStopped, padapter->bSurpriseRemoved); - res = false; - } else - res = true; - - return res; -} - -void rtw_generate_random_ibss23a(u8 *pibss) -{ - unsigned long curtime = jiffies; - - pibss[0] = 0x02; /* in ad-hoc mode bit1 must set to 1 */ - pibss[1] = 0x11; - pibss[2] = 0x87; - pibss[3] = curtime & 0xff;/* p[0]; */ - pibss[4] = (curtime >> 8) & 0xff;/* p[1]; */ - pibss[5] = (curtime >> 16) & 0xff;/* p[2]; */ -} - -void rtw_set_roaming(struct rtw_adapter *adapter, u8 to_roaming) -{ - if (to_roaming == 0) - adapter->mlmepriv.to_join = false; - adapter->mlmepriv.to_roaming = to_roaming; -} - -static void _rtw_roaming(struct rtw_adapter *padapter, - struct wlan_network *tgt_network) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *pnetwork; - int do_join_r; - - if (tgt_network) - pnetwork = tgt_network; - else - pnetwork = &pmlmepriv->cur_network; - - if (padapter->mlmepriv.to_roaming > 0) { - DBG_8723A("roaming from %s(%pM), length:%d\n", - pnetwork->network.Ssid.ssid, - pnetwork->network.MacAddress, - pnetwork->network.Ssid.ssid_len); - memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid, - sizeof(struct cfg80211_ssid)); - - pmlmepriv->assoc_by_bssid = false; - - while (1) { - do_join_r = rtw_do_join(padapter); - if (do_join_r == _SUCCESS) - break; - else { - DBG_8723A("roaming do_join return %d\n", - do_join_r); - pmlmepriv->to_roaming--; - - if (padapter->mlmepriv.to_roaming > 0) - continue; - else { - DBG_8723A("%s(%d) -to roaming fail, " - "indicate_disconnect\n", - __func__, __LINE__); - rtw_indicate_disconnect23a(padapter); - break; - } - } - } - } -} - -void rtw23a_roaming(struct rtw_adapter *padapter, - struct wlan_network *tgt_network) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - spin_lock_bh(&pmlmepriv->lock); - _rtw_roaming(padapter, tgt_network); - spin_unlock_bh(&pmlmepriv->lock); -} - -static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv, - struct wlan_network *pnetwork) -{ - _rtw_free_network23a(pmlmepriv, pnetwork); -} - -bool rtw_is_same_ibss23a(struct rtw_adapter *adapter, - struct wlan_network *pnetwork) -{ - int ret; - struct security_priv *psecuritypriv = &adapter->securitypriv; - - if (psecuritypriv->dot11PrivacyAlgrthm != 0 && - pnetwork->network.Privacy == 0) - ret = false; - else if (psecuritypriv->dot11PrivacyAlgrthm == 0 && - pnetwork->network.Privacy == 1) - ret = false; - else - ret = true; - - return ret; -} - -inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b); -inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b) -{ - return (a->Ssid.ssid_len == b->Ssid.ssid_len) && - !memcmp(a->Ssid.ssid, b->Ssid.ssid, a->Ssid.ssid_len); -} - -int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst) -{ - u16 s_cap, d_cap; - - s_cap = src->capability; - d_cap = dst->capability; - - return ((src->Ssid.ssid_len == dst->Ssid.ssid_len) && - /* (src->DSConfig == dst->DSConfig) && */ - ether_addr_equal(src->MacAddress, dst->MacAddress) && - !memcmp(src->Ssid.ssid, dst->Ssid.ssid, src->Ssid.ssid_len) && - (s_cap & WLAN_CAPABILITY_IBSS) == - (d_cap & WLAN_CAPABILITY_IBSS) && - (s_cap & WLAN_CAPABILITY_ESS) == (d_cap & WLAN_CAPABILITY_ESS)); -} - -struct wlan_network * -rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_queue) -{ - struct list_head *phead; - struct wlan_network *pwlan; - struct wlan_network *oldest = NULL; - - phead = get_list_head(scanned_queue); - list_for_each_entry(pwlan, phead, list) { - if (pwlan->fixed != true) { - if (!oldest || time_after(oldest->last_scanned, - pwlan->last_scanned)) - oldest = pwlan; - } - } - - return oldest; -} - -void update_network23a(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src, - struct rtw_adapter *padapter, bool update_ie) -{ - u8 ss_ori = dst->SignalStrength; - u8 sq_ori = dst->SignalQuality; - long rssi_ori = dst->Rssi; - - u8 ss_smp = src->SignalStrength; - u8 sq_smp = src->SignalQuality; - long rssi_smp = src->Rssi; - - u8 ss_final; - u8 sq_final; - long rssi_final; - - DBG_8723A("%s %s(%pM, ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, " - "ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n", - __func__, src->Ssid.ssid, src->MacAddress, - src->DSConfig, ss_ori, sq_ori, rssi_ori, - ss_smp, sq_smp, rssi_smp - ); - - /* The rule below is 1/5 for sample value, 4/5 for history value */ - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && - is_same_network23a(&padapter->mlmepriv.cur_network.network, src)) { - /* Take the recvpriv's value for the connected AP*/ - ss_final = padapter->recvpriv.signal_strength; - sq_final = padapter->recvpriv.signal_qual; - /* the rssi value here is undecorated, and will be - used for antenna diversity */ - if (sq_smp != 101) /* from the right channel */ - rssi_final = (src->Rssi+dst->Rssi*4)/5; - else - rssi_final = rssi_ori; - } else { - if (sq_smp != 101) { /* from the right channel */ - ss_final = ((u32)src->SignalStrength + - (u32)dst->SignalStrength * 4) / 5; - sq_final = ((u32)src->SignalQuality + - (u32)dst->SignalQuality * 4) / 5; - rssi_final = src->Rssi+dst->Rssi * 4 / 5; - } else { - /* bss info not receiving from the right channel, use - the original RX signal infos */ - ss_final = dst->SignalStrength; - sq_final = dst->SignalQuality; - rssi_final = dst->Rssi; - } - - } - - if (update_ie) - memcpy(dst, src, get_wlan_bssid_ex_sz(src)); - - dst->SignalStrength = ss_final; - dst->SignalQuality = sq_final; - dst->Rssi = rssi_final; - - DBG_8723A("%s %s(%pM), SignalStrength:%u, SignalQuality:%u, " - "RawRSSI:%ld\n", __func__, dst->Ssid.ssid, dst->MacAddress, - dst->SignalStrength, dst->SignalQuality, dst->Rssi); -} - -static void update_current_network(struct rtw_adapter *adapter, - struct wlan_bssid_ex *pnetwork) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - if (check_fwstate(pmlmepriv, _FW_LINKED) && - is_same_network23a(&pmlmepriv->cur_network.network, pnetwork)) { - update_network23a(&pmlmepriv->cur_network.network, - pnetwork, adapter, true); - - rtw_update_protection23a(adapter, - pmlmepriv->cur_network.network.IEs, - pmlmepriv->cur_network.network.IELength); - } -} - -/* - -Caller must hold pmlmepriv->lock first. - -*/ -static void rtw_update_scanned_network(struct rtw_adapter *adapter, - struct wlan_bssid_ex *target) -{ - struct list_head *plist, *phead; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_network *pnetwork = NULL; - struct wlan_network *oldest = NULL; - struct rtw_queue *queue = &pmlmepriv->scanned_queue; - u32 bssid_ex_sz; - int found = 0; - - spin_lock_bh(&queue->lock); - phead = get_list_head(queue); - list_for_each(plist, phead) { - pnetwork = container_of(plist, struct wlan_network, list); - - if (is_same_network23a(&pnetwork->network, target)) { - found = 1; - break; - } - if (!oldest || time_after(oldest->last_scanned, - pnetwork->last_scanned)) - oldest = pnetwork; - } - - /* If we didn't find a match, then get a new network slot to initialize - * with this beacon's information */ - if (!found) { - pnetwork = rtw_alloc_network(pmlmepriv, GFP_ATOMIC); - if (!pnetwork) { - if (!oldest) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "something wrong here\n"); - goto exit; - } - pnetwork = oldest; - } else - list_add_tail(&pnetwork->list, &queue->queue); - - bssid_ex_sz = get_wlan_bssid_ex_sz(target); - target->Length = bssid_ex_sz; - memcpy(&pnetwork->network, target, bssid_ex_sz); - - /* variable initialize */ - pnetwork->fixed = false; - pnetwork->last_scanned = jiffies; - - pnetwork->network_type = 0; - pnetwork->join_res = 0; - - /* bss info not receiving from the right channel */ - if (pnetwork->network.SignalQuality == 101) - pnetwork->network.SignalQuality = 0; - } else { - /* - * we have an entry and we are going to update it. But - * this entry may be already expired. In this case we - * do the same as we found a new net and call the - * new_net handler - */ - bool update_ie = true; - - pnetwork->last_scanned = jiffies; - - /* target.reserved == 1, means that scanned network is - * a bcn frame. */ - if (pnetwork->network.IELength > target->IELength && - target->reserved == 1) - update_ie = false; - - update_network23a(&pnetwork->network, target, adapter, - update_ie); - } - -exit: - spin_unlock_bh(&queue->lock); -} - -static void rtw_add_network(struct rtw_adapter *adapter, - struct wlan_bssid_ex *pnetwork) -{ - update_current_network(adapter, pnetwork); - rtw_update_scanned_network(adapter, pnetwork); -} - -/* select the desired network based on the capability of the (i)bss. */ -/* check items: (1) security */ -/* (2) network_type */ -/* (3) WMM */ -/* (4) HT */ -/* (5) others */ -static int rtw_is_desired_network(struct rtw_adapter *adapter, - struct wlan_network *pnetwork) -{ - struct security_priv *psecuritypriv = &adapter->securitypriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u32 desired_encmode; - u32 privacy; - int bselected = true; - - desired_encmode = psecuritypriv->ndisencryptstatus; - privacy = pnetwork->network.Privacy; - - if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) { - if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - pnetwork->network.IEs, - pnetwork->network.IELength)) - return true; - else - return false; - } - if (adapter->registrypriv.wifi_spec == 1) { - /* for correct flow of 8021X to do.... */ - if (desired_encmode == Ndis802_11EncryptionDisabled && - privacy != 0) - bselected = false; - } - - if (desired_encmode != Ndis802_11EncryptionDisabled && privacy == 0) { - DBG_8723A("desired_encmode: %d, privacy: %d\n", - desired_encmode, privacy); - bselected = false; - } - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - if (pnetwork->network.ifmode != - pmlmepriv->cur_network.network.ifmode) - bselected = false; - } - - return bselected; -} - -void rtw_survey_event_cb23a(struct rtw_adapter *adapter, const u8 *pbuf) -{ - u32 len; - struct wlan_bssid_ex *pnetwork; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct survey_event *survey = (struct survey_event *)pbuf; - - pnetwork = survey->bss; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw_survey_event_cb23a, ssid=%s\n", pnetwork->Ssid.ssid); - - len = get_wlan_bssid_ex_sz(pnetwork); - if (len > (sizeof(struct wlan_bssid_ex))) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "****rtw_survey_event_cb23a: return a wrong bss ***\n"); - return; - } - - spin_lock_bh(&pmlmepriv->lock); - - /* update IBSS_network 's timestamp */ - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - if (ether_addr_equal(pmlmepriv->cur_network.network.MacAddress, - pnetwork->MacAddress)) { - struct wlan_network *ibss_wlan; - - pmlmepriv->cur_network.network.beacon_interval = - pnetwork->beacon_interval; - pmlmepriv->cur_network.network.capability = - pnetwork->capability; - pmlmepriv->cur_network.network.tsf = pnetwork->tsf; - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - ibss_wlan = rtw_find_network23a( - &pmlmepriv->scanned_queue, - pnetwork->MacAddress); - if (ibss_wlan) { - pmlmepriv->cur_network.network.beacon_interval = - ibss_wlan->network.beacon_interval; - pmlmepriv->cur_network.network.capability = - ibss_wlan->network.capability; - pmlmepriv->cur_network.network.tsf = - ibss_wlan->network.tsf; - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto exit; - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - } - } - - /* lock pmlmepriv->lock when you accessing network_q */ - if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - if (pnetwork->Ssid.ssid[0] == 0) - pnetwork->Ssid.ssid_len = 0; - - rtw_add_network(adapter, pnetwork); - } - -exit: - - spin_unlock_bh(&pmlmepriv->lock); - - kfree(survey->bss); - survey->bss = NULL; -} - -void -rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - int ret; - - spin_lock_bh(&pmlmepriv->lock); - - if (pmlmepriv->wps_probe_req_ie) { - pmlmepriv->wps_probe_req_ie_len = 0; - kfree(pmlmepriv->wps_probe_req_ie); - pmlmepriv->wps_probe_req_ie = NULL; - } - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw_surveydone_event_callback23a: fw_state:%x\n", - get_fwstate(pmlmepriv)); - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { - del_timer_sync(&pmlmepriv->scan_to_timer); - - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - } else { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "nic status =%x, survey done event comes too late!\n", - get_fwstate(pmlmepriv)); - } - - rtw_set_signal_stat_timer(&adapter->recvpriv); - - if (pmlmepriv->to_join == true) { - set_fwstate(pmlmepriv, _FW_UNDER_LINKING); - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - ret = rtw_select_and_join_from_scanned_queue23a( - pmlmepriv); - if (ret != _SUCCESS) - rtw_do_join_adhoc(adapter); - } else { - pmlmepriv->to_join = false; - ret = rtw_select_and_join_from_scanned_queue23a( - pmlmepriv); - if (ret != _SUCCESS) { - DBG_8723A("try_to_join, but select scanning " - "queue fail, to_roaming:%d\n", - adapter->mlmepriv.to_roaming); - if (adapter->mlmepriv.to_roaming) { - if (--pmlmepriv->to_roaming == 0 || - rtw_sitesurvey_cmd23a( - adapter, - &pmlmepriv->assoc_ssid, 1, - NULL, 0) != _SUCCESS) { - rtw_set_roaming(adapter, 0); - rtw_free_assoc_resources23a( - adapter, 1); - rtw_indicate_disconnect23a( - adapter); - } else - pmlmepriv->to_join = true; - } - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - } - } - } - - spin_unlock_bh(&pmlmepriv->lock); - - rtw_os_xmit_schedule23a(adapter); - - if (pmlmeext->sitesurvey_res.bss_cnt == 0) - rtw_sreset_reset(adapter); - - rtw_cfg80211_surveydone_event_callback(adapter); -} - -static void free_scanqueue(struct mlme_priv *pmlmepriv) -{ - struct wlan_network *pnetwork, *ptemp; - struct rtw_queue *scan_queue = &pmlmepriv->scanned_queue; - struct list_head *phead; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, "+free_scanqueue\n"); - spin_lock_bh(&scan_queue->lock); - phead = get_list_head(scan_queue); - list_for_each_entry_safe(pnetwork, ptemp, phead, list) { - pnetwork->fixed = false; - _rtw_free_network23a(pmlmepriv, pnetwork); - } - spin_unlock_bh(&scan_queue->lock); -} - -/* - *rtw_free_assoc_resources23a: the caller has to lock pmlmepriv->lock - */ -void rtw_free_assoc_resources23a(struct rtw_adapter *adapter, - int lock_scanned_queue) -{ - struct wlan_network *pwlan; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct sta_priv *pstapriv = &adapter->stapriv; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - struct sta_info *psta; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - "+rtw_free_assoc_resources23a\n"); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "tgt_network->network.MacAddress=%pM ssid=%s\n", - tgt_network->network.MacAddress, - tgt_network->network.Ssid.ssid); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE)) { - psta = rtw_get_stainfo23a(&adapter->stapriv, - tgt_network->network.MacAddress); - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(adapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - } - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | - WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) { - rtw_free_all_stainfo23a(adapter); - - psta = rtw_get_bcmc_stainfo23a(adapter); - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(adapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - rtw_init_bcmc_stainfo23a(adapter); - } - - if (lock_scanned_queue) - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - - pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, - tgt_network->network.MacAddress); - if (pwlan) - pwlan->fixed = false; - else - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_free_assoc_resources23a : pwlan== NULL\n"); - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && - adapter->stapriv.asoc_sta_count == 1) - rtw_free_network_nolock(pmlmepriv, pwlan); - - if (lock_scanned_queue) - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - pmlmepriv->key_mask = 0; -} - -/* -*rtw_indicate_connect23a: the caller has to lock pmlmepriv->lock -*/ -void rtw_indicate_connect23a(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "+rtw_indicate_connect23a\n"); - - pmlmepriv->to_join = false; - - if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { - set_fwstate(pmlmepriv, _FW_LINKED); - - rtw_cfg80211_indicate_connect(padapter); - - netif_carrier_on(padapter->pnetdev); - - if (padapter->pid[2] != 0) - kill_pid(find_vpid(padapter->pid[2]), SIGALRM, 1); - } - - rtw_set_roaming(padapter, 0); - - rtw_set_scan_deny(padapter, 3000); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "-rtw_indicate_connect23a: fw_state=0x%08x\n", - get_fwstate(pmlmepriv)); -} - -/* - *rtw_indicate_disconnect23a: the caller has to lock pmlmepriv->lock - */ -void rtw_indicate_disconnect23a(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "+rtw_indicate_disconnect23a\n"); - - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS); - - /* DBG_8723A("clear wps when %s\n", __func__); */ - - if (padapter->mlmepriv.to_roaming > 0) - _clr_fwstate_(pmlmepriv, _FW_LINKED); - - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) || - padapter->mlmepriv.to_roaming <= 0) { - rtw_os_indicate_disconnect23a(padapter); - - /* set ips_deny_time to avoid enter IPS before LPS leave */ - padapter->pwrctrlpriv.ips_deny_time = - jiffies + msecs_to_jiffies(3000); - - _clr_fwstate_(pmlmepriv, _FW_LINKED); - - rtw_clear_scan_deny(padapter); - } - - rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_DISCONNECT, 1); -} - -void rtw_scan_abort23a(struct rtw_adapter *adapter) -{ - unsigned long start; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - - start = jiffies; - pmlmeext->scan_abort = true; - while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) && - jiffies_to_msecs(jiffies - start) <= 200) { - if (adapter->bDriverStopped || adapter->bSurpriseRemoved) - break; - - DBG_8723A("%s(%s): fw_state = _FW_UNDER_SURVEY!\n", - __func__, adapter->pnetdev->name); - msleep(20); - } - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { - if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved) - DBG_8723A("%s(%s): waiting for scan_abort time out!\n", - __func__, adapter->pnetdev->name); - rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev), - true); - } - pmlmeext->scan_abort = false; -} - -static struct sta_info * -rtw_joinbss_update_stainfo(struct rtw_adapter *padapter, - struct wlan_network *pnetwork) -{ - int i; - struct sta_info *bmc_sta, *psta; - struct recv_reorder_ctrl *preorder_ctrl; - struct sta_priv *pstapriv = &padapter->stapriv; - - psta = rtw_get_stainfo23a(pstapriv, pnetwork->network.MacAddress); - if (!psta) - psta = rtw_alloc_stainfo23a(pstapriv, - pnetwork->network.MacAddress, - GFP_ATOMIC); - - if (psta) { /* update ptarget_sta */ - DBG_8723A("%s\n", __func__); - - psta->aid = pnetwork->join_res; - psta->mac_id = 0; - - /* sta mode */ - rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, true); - - /* security related */ - if (padapter->securitypriv.dot11AuthAlgrthm == - dot11AuthAlgrthm_8021X) { - padapter->securitypriv.binstallGrpkey = 0; - padapter->securitypriv.busetkipkey = 0; - - psta->ieee8021x_blocked = true; - psta->dot118021XPrivacy = - padapter->securitypriv.dot11PrivacyAlgrthm; - - memset(&psta->dot118021x_UncstKey, 0, - sizeof (union Keytype)); - - memset(&psta->dot11tkiprxmickey, 0, - sizeof (union Keytype)); - memset(&psta->dot11tkiptxmickey, 0, - sizeof (union Keytype)); - - memset(&psta->dot11txpn, 0, sizeof (union pn48)); - memset(&psta->dot11rxpn, 0, sizeof (union pn48)); - } - - /* Commented by Albert 2012/07/21 */ - /* When doing the WPS, the wps_ie_len won't equal to 0 */ - /* And the Wi-Fi driver shouldn't allow the data packet - to be transmitted. */ - if (padapter->securitypriv.wps_ie_len != 0) { - psta->ieee8021x_blocked = true; - padapter->securitypriv.wps_ie_len = 0; - } - - /* for A-MPDU Rx reordering buffer control for bmc_sta & - * sta_info */ - /* if A-MPDU Rx is enabled, resetting - rx_ordering_ctrl wstart_b(indicate_seq) to default - value = 0xffff */ - /* todo: check if AP can send A-MPDU packets */ - for (i = 0; i < 16 ; i++) { - /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */ - preorder_ctrl = &psta->recvreorder_ctrl[i]; - preorder_ctrl->enable = false; - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - /* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */ - preorder_ctrl->wsize_b = 64; - } - - bmc_sta = rtw_get_bcmc_stainfo23a(padapter); - if (bmc_sta) { - for (i = 0; i < 16 ; i++) { - preorder_ctrl = &bmc_sta->recvreorder_ctrl[i]; - preorder_ctrl->enable = false; - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - /* max_ampdu_sz; ex. 32(kbytes) -> - wsize_b = 32 */ - preorder_ctrl->wsize_b = 64; - } - } - - /* misc. */ - update_sta_info23a(padapter, psta); - - } - - return psta; -} - -/* pnetwork : returns from rtw23a_joinbss_event_cb */ -/* ptarget_wlan: found from scanned_queue */ -static void -rtw_joinbss_update_network23a(struct rtw_adapter *padapter, - struct wlan_network *ptarget_wlan, - struct wlan_network *pnetwork) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - - DBG_8723A("%s\n", __func__); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "fw_state:%x, BSSID:%pM\n", - get_fwstate(pmlmepriv), - pnetwork->network.MacAddress); - - /* why not use ptarget_wlan?? */ - memcpy(&cur_network->network, &pnetwork->network, - pnetwork->network.Length); - /* some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */ - cur_network->network.IELength = ptarget_wlan->network.IELength; - memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0], - MAX_IE_SZ); - - cur_network->network.capability = ptarget_wlan->network.capability; - cur_network->network.beacon_interval = - ptarget_wlan->network.beacon_interval; - cur_network->network.tsf = ptarget_wlan->network.tsf; - - rtw_set_signal_stat_timer(&padapter->recvpriv); - padapter->recvpriv.signal_strength = - ptarget_wlan->network.SignalStrength; - padapter->recvpriv.signal_qual = ptarget_wlan->network.SignalQuality; - /* - * the ptarget_wlan->network.Rssi is raw data, we use - * ptarget_wlan->network.SignalStrength instead (has scaled) - */ - DBG_8723A("%s signal_strength:%3u, signal_qual:%3u\n", - __func__, padapter->recvpriv.signal_strength, - padapter->recvpriv.signal_qual); - rtw_set_signal_stat_timer(&padapter->recvpriv); - - /* update fw_state will clr _FW_UNDER_LINKING here indirectly */ - switch (pnetwork->network.ifmode) { - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - if (pmlmepriv->fw_state & WIFI_UNDER_WPS) - pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS; - else - pmlmepriv->fw_state = WIFI_STATION_STATE; - break; - case NL80211_IFTYPE_ADHOC: - pmlmepriv->fw_state = WIFI_ADHOC_STATE; - break; - default: - pmlmepriv->fw_state = WIFI_NULL_STATE; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Invalid network_mode\n"); - break; - } - - rtw_update_protection23a(padapter, cur_network->network.IEs, - cur_network->network.IELength); - - rtw_update_ht_cap23a(padapter, cur_network->network.IEs, - cur_network->network.IELength); -} - -/* - * Notes: - * the function could be > passive_level (the same context as Rx tasklet) - * pnetwork : returns from rtw23a_joinbss_event_cb - * ptarget_wlan: found from scanned_queue - * if join_res > 0, for (fw_state==WIFI_STATION_STATE), - * we check if "ptarget_sta" & "ptarget_wlan" exist. - * if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), - * we only check if "ptarget_wlan" exist. - * if join_res > 0, update "cur_network->network" from "pnetwork->network" - * if (ptarget_wlan !=NULL). - */ - -void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf) -{ - struct sta_info *ptarget_sta, *pcur_sta; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_network *pnetwork = (struct wlan_network *)pbuf; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct wlan_network *pcur_wlan, *ptarget_wlan = NULL; - bool the_same_macaddr; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "joinbss event call back received with res=%d\n", - pnetwork->join_res); - - if (pmlmepriv->assoc_ssid.ssid_len == 0) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "@@@@@ joinbss event call back for Any SSid\n"); - } else { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "@@@@@ rtw23a_joinbss_event_cb for SSid:%s\n", - pmlmepriv->assoc_ssid.ssid); - } - - if (ether_addr_equal(pnetwork->network.MacAddress, - cur_network->network.MacAddress)) - the_same_macaddr = true; - else - the_same_macaddr = false; - - pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network); - if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "***joinbss_evt_callback return a wrong bss ***\n"); - return; - } - - spin_lock_bh(&pmlmepriv->lock); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "rtw23a_joinbss_event_cb !! _enter_critical\n"); - - if (pnetwork->join_res > 0) { - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - /* s1. find ptarget_wlan */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - if (the_same_macaddr) { - ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress); - } else { - pcur_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress); - if (pcur_wlan) - pcur_wlan->fixed = false; - - pcur_sta = rtw_get_stainfo23a(pstapriv, cur_network->network.MacAddress); - if (pcur_sta) { - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(adapter, - pcur_sta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - } - - ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress); - if (check_fwstate(pmlmepriv, - WIFI_STATION_STATE)) { - if (ptarget_wlan) - ptarget_wlan->fixed = - true; - } - } - - } else { - ptarget_wlan = rtw_find_network23a( - &pmlmepriv->scanned_queue, - pnetwork->network.MacAddress); - if (check_fwstate(pmlmepriv, - WIFI_STATION_STATE)) { - if (ptarget_wlan) - ptarget_wlan->fixed = true; - } - } - - /* s2. update cur_network */ - if (ptarget_wlan) - rtw_joinbss_update_network23a(adapter, - ptarget_wlan, - pnetwork); - else { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Can't find ptarget_wlan when joinbss_event callback\n"); - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto ignore_joinbss_callback; - } - - /* s3. find ptarget_sta & update ptarget_sta after - update cur_network only for station mode */ - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - ptarget_sta = rtw_joinbss_update_stainfo( - adapter, pnetwork); - if (!ptarget_sta) { - RT_TRACE(_module_rtl871x_mlme_c_, - _drv_err_, - "Can't update stainfo when joinbss_event callback\n"); - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto ignore_joinbss_callback; - } - } - - /* s4. indicate connect */ - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - rtw_indicate_connect23a(adapter); - else { - /* adhoc mode will rtw_indicate_connect23a - when rtw_stassoc_event_callback23a */ - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "adhoc mode, fw_state:%x\n", - get_fwstate(pmlmepriv)); - } - - /* s5. Cancle assoc_timer */ - del_timer_sync(&pmlmepriv->assoc_timer); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "Cancle assoc_timer\n"); - } else { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw23a_joinbss_event_cb err: fw_state:%x\n", - get_fwstate(pmlmepriv)); - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - goto ignore_joinbss_callback; - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - } else if (pnetwork->join_res == -4) { - rtw_reset_securitypriv23a(adapter); - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(1)); - - /* rtw_free_assoc_resources23a(adapter, 1); */ - - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "fail! clear _FW_UNDER_LINKING ^^^fw_state=%x\n", - get_fwstate(pmlmepriv)); - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - } - } else { - /* if join_res < 0 (join fails), then try again */ - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(1)); - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - } - -ignore_joinbss_callback: - - spin_unlock_bh(&pmlmepriv->lock); -} - -void rtw23a_joinbss_event_cb(struct rtw_adapter *adapter, const u8 *pbuf) -{ - struct wlan_network *pnetwork = (struct wlan_network *)pbuf; - - mlmeext_joinbss_event_callback23a(adapter, pnetwork->join_res); - - rtw_os_xmit_schedule23a(adapter); -} - -void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf) -{ - struct sta_info *psta; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct wlan_network *ptarget_wlan; - - if (rtw_access_ctrl23a(adapter, pstassoc->macaddr) == false) - return; - -#ifdef CONFIG_8723AU_AP_MODE - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr); - if (psta) { - /* bss_cap_update_on_sta_join23a(adapter, psta); */ - /* sta_info_update23a(adapter, psta); */ - ap_sta_info_defer_update23a(adapter, psta); - } - return; - } -#endif - /* for AD-HOC mode */ - psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr); - if (psta != NULL) { - /* the sta have been in sta_info_queue => do nothing */ - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Error: rtw_stassoc_event_callback23a: sta has been in sta_hash_queue\n"); - /* between drv has received this event before and - fw have not yet to set key to CAM_ENTRY) */ - return; - } - - psta = rtw_alloc_stainfo23a(&adapter->stapriv, pstassoc->macaddr, - GFP_KERNEL); - if (!psta) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Can't alloc sta_info when rtw_stassoc_event_callback23a\n"); - return; - } - - /* to do : init sta_info variable */ - psta->qos_option = 0; - psta->mac_id = (uint)pstassoc->cam_id; - /* psta->aid = (uint)pstassoc->cam_id; */ - DBG_8723A("%s\n", __func__); - /* for ad-hoc mode */ - rtl8723a_SetHalODMVar(adapter, HAL_ODM_STA_INFO, psta, true); - - if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) - psta->dot118021XPrivacy = - adapter->securitypriv.dot11PrivacyAlgrthm; - - psta->ieee8021x_blocked = false; - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - if (adapter->stapriv.asoc_sta_count == 2) { - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - ptarget_wlan = - rtw_find_network23a(&pmlmepriv->scanned_queue, - cur_network->network.MacAddress); - if (ptarget_wlan) - ptarget_wlan->fixed = true; - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - /* a sta + bc/mc_stainfo (not Ibss_stainfo) */ - rtw_indicate_connect23a(adapter); - } - } - - spin_unlock_bh(&pmlmepriv->lock); - - mlmeext_sta_add_event_callback23a(adapter, psta); -} - -void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, const u8 *pbuf) -{ - int mac_id; - struct sta_info *psta; - struct wlan_network *pwlan; - struct wlan_bssid_ex *pdev_network; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct stadel_event *pstadel = (struct stadel_event *)pbuf; - struct sta_priv *pstapriv = &adapter->stapriv; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - - psta = rtw_get_stainfo23a(&adapter->stapriv, pstadel->macaddr); - if (psta) - mac_id = psta->mac_id; - else - mac_id = pstadel->mac_id; - - DBG_8723A("%s(mac_id=%d)=%pM\n", __func__, mac_id, pstadel->macaddr); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return; - - mlmeext_sta_del_event_callback23a(adapter); - - spin_lock_bh(&pmlmepriv->lock); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - if (adapter->mlmepriv.to_roaming > 0) { - /* this stadel_event is caused by roaming, - decrease to_roaming */ - pmlmepriv->to_roaming--; - } else if (adapter->mlmepriv.to_roaming == 0) - rtw_set_roaming(adapter, adapter->registrypriv.max_roaming_times); - if (*((u16 *)pstadel->rsvd) != WLAN_REASON_EXPIRATION_CHK) - rtw_set_roaming(adapter, 0); /* don't roam */ - - rtw_free_uc_swdec_pending_queue23a(adapter); - - rtw_free_assoc_resources23a(adapter, 1); - rtw_indicate_disconnect23a(adapter); - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - /* remove the network entry in scanned_queue */ - pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, - tgt_network->network.MacAddress); - if (pwlan) { - pwlan->fixed = false; - rtw_free_network_nolock(pmlmepriv, pwlan); - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - _rtw_roaming(adapter, tgt_network); - } - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - - spin_lock_bh(&pstapriv->sta_hash_lock); - rtw_free_stainfo23a(adapter, psta); - spin_unlock_bh(&pstapriv->sta_hash_lock); - - /* a sta + bc/mc_stainfo (not Ibss_stainfo) */ - if (adapter->stapriv.asoc_sta_count == 1) { - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - /* free old ibss network */ - /* pwlan = rtw_find_network23a( - &pmlmepriv->scanned_queue, pstadel->macaddr); */ - pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, - tgt_network->network.MacAddress); - if (pwlan) { - pwlan->fixed = false; - rtw_free_network_nolock(pmlmepriv, pwlan); - } - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - /* re-create ibss */ - pdev_network = &adapter->registrypriv.dev_network; - - memcpy(pdev_network, &tgt_network->network, - get_wlan_bssid_ex_sz(&tgt_network->network)); - - rtw_do_join_adhoc(adapter); - } - } - - spin_unlock_bh(&pmlmepriv->lock); -} - -/* -* rtw23a_join_to_handler - Timeout/failure handler for CMD JoinBss -* @adapter: pointer to _adapter structure -*/ -void rtw23a_join_to_handler (unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - int do_join_r; - - DBG_8723A("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv)); - - if (adapter->bDriverStopped || adapter->bSurpriseRemoved) - return; - - spin_lock_bh(&pmlmepriv->lock); - - if (adapter->mlmepriv.to_roaming > 0) { - /* join timeout caused by roaming */ - while (1) { - pmlmepriv->to_roaming--; - if (adapter->mlmepriv.to_roaming != 0) { - /* try another */ - DBG_8723A("%s try another roaming\n", __func__); - do_join_r = rtw_do_join(adapter); - if (do_join_r != _SUCCESS) { - DBG_8723A("%s roaming do_join return " - "%d\n", __func__ , do_join_r); - continue; - } - break; - } else { - DBG_8723A("%s We've try roaming but fail\n", - __func__); - rtw_indicate_disconnect23a(adapter); - break; - } - } - } else { - rtw_indicate_disconnect23a(adapter); - free_scanqueue(pmlmepriv);/* */ - - /* indicate disconnect for the case that join_timeout and - check_fwstate != FW_LINKED */ - rtw_cfg80211_indicate_disconnect(adapter); - } - - spin_unlock_bh(&pmlmepriv->lock); - -} - -/* -* rtw_scan_timeout_handler23a - Timeout/Failure handler for CMD SiteSurvey -* @data: pointer to _adapter structure -*/ -void rtw_scan_timeout_handler23a(unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - DBG_8723A("%s(%s): fw_state =%x\n", __func__, adapter->pnetdev->name, - get_fwstate(pmlmepriv)); - - spin_lock_bh(&pmlmepriv->lock); - - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - - spin_unlock_bh(&pmlmepriv->lock); - - rtw_cfg80211_indicate_scan_done(wdev_to_priv(adapter->rtw_wdev), true); -} - -void rtw_dynamic_check_timer_handler(unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - - if (adapter->hw_init_completed == false) - goto out; - - if (adapter->bDriverStopped == true || - adapter->bSurpriseRemoved == true) - goto out; - - if (adapter->net_closed == true) - goto out; - - rtw_dynamic_chk_wk_cmd23a(adapter); - -out: - mod_timer(&adapter->mlmepriv.dynamic_chk_timer, - jiffies + msecs_to_jiffies(2000)); -} - -inline bool rtw_is_scan_deny(struct rtw_adapter *adapter) -{ - struct mlme_priv *mlmepriv = &adapter->mlmepriv; - - return (atomic_read(&mlmepriv->set_scan_deny) != 0) ? true : false; -} - -void rtw_clear_scan_deny(struct rtw_adapter *adapter) -{ - struct mlme_priv *mlmepriv = &adapter->mlmepriv; - - atomic_set(&mlmepriv->set_scan_deny, 0); -} - -void rtw_set_scan_deny_timer_hdl(unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - - rtw_clear_scan_deny(adapter); -} - -void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms) -{ - struct mlme_priv *mlmepriv = &adapter->mlmepriv; - - atomic_set(&mlmepriv->set_scan_deny, 1); - mod_timer(&mlmepriv->set_scan_deny_timer, - jiffies + msecs_to_jiffies(ms)); -} - -#if defined(IEEE80211_SCAN_RESULT_EXPIRE) -#define RTW_SCAN_RESULT_EXPIRE \ - ((IEEE80211_SCAN_RESULT_EXPIRE / (HZ*1000)) - 1000) /* 3000 -1000 */ -#else -#define RTW_SCAN_RESULT_EXPIRE 2000 -#endif - -/* -* Select a new join candidate from the original @param candidate and -* @param competitor -* @return true: candidate is updated -* @return false: candidate is not updated -*/ -static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv, - struct wlan_network **candidate, - struct wlan_network *competitor) -{ - int updated = false; - struct rtw_adapter *adapter; - - adapter = container_of(pmlmepriv, struct rtw_adapter, mlmepriv); - - /* check bssid, if needed */ - if (pmlmepriv->assoc_by_bssid == true) { - if (!ether_addr_equal(competitor->network.MacAddress, - pmlmepriv->assoc_bssid)) - goto exit; - } - - /* check ssid, if needed */ - if (pmlmepriv->assoc_ssid.ssid_len) { - if (competitor->network.Ssid.ssid_len != - pmlmepriv->assoc_ssid.ssid_len || - memcmp(competitor->network.Ssid.ssid, - pmlmepriv->assoc_ssid.ssid, - pmlmepriv->assoc_ssid.ssid_len)) - goto exit; - } - - if (rtw_is_desired_network(adapter, competitor) == false) - goto exit; - - if (adapter->mlmepriv.to_roaming > 0) { - unsigned int passed; - - passed = jiffies_to_msecs(jiffies - competitor->last_scanned); - if (passed >= RTW_SCAN_RESULT_EXPIRE || - is_same_ess(&competitor->network, - &pmlmepriv->cur_network.network) == false) - goto exit; - } - - if (!*candidate || - (*candidate)->network.Rssi<competitor->network.Rssi) { - *candidate = competitor; - updated = true; - } - - if (updated) { - DBG_8723A("[by_bssid:%u][assoc_ssid:%s][to_roaming:%u] new candidate: %s(%pM) rssi:%d\n", - pmlmepriv->assoc_by_bssid, - pmlmepriv->assoc_ssid.ssid, - adapter->mlmepriv.to_roaming, - (*candidate)->network.Ssid.ssid, - (*candidate)->network.MacAddress, - (int)(*candidate)->network.Rssi); - } - -exit: - return updated; -} - -/* -Calling context: -The caller of the sub-routine will be in critical section... - -The caller must hold the following spinlock - -pmlmepriv->lock - -*/ - -static int rtw_do_join(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int ret; - - pmlmepriv->cur_network.join_res = -2; - - set_fwstate(pmlmepriv, _FW_UNDER_LINKING); - - pmlmepriv->to_join = true; - - ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv); - if (ret == _SUCCESS) { - pmlmepriv->to_join = false; - } else { - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - /* switch to ADHOC_MASTER */ - ret = rtw_do_join_adhoc(padapter); - if (ret != _SUCCESS) - goto exit; - } else { - /* can't associate ; reset under-linking */ - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - - ret = _FAIL; - pmlmepriv->to_join = false; - } - } - -exit: - return ret; -} - -static struct wlan_network * -rtw_select_candidate_from_queue(struct mlme_priv *pmlmepriv) -{ - struct wlan_network *pnetwork, *ptmp, *candidate = NULL; - struct rtw_queue *queue = &pmlmepriv->scanned_queue; - struct list_head *phead; - - spin_lock_bh(&pmlmepriv->scanned_queue.lock); - phead = get_list_head(queue); - list_for_each_entry_safe(pnetwork, ptmp, phead, list) - rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork); - spin_unlock_bh(&pmlmepriv->scanned_queue.lock); - - return candidate; -} - - -int rtw_do_join_adhoc(struct rtw_adapter *adapter) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_bssid_ex *pdev_network; - u8 *ibss; - int ret; - - pdev_network = &adapter->registrypriv.dev_network; - ibss = adapter->registrypriv.dev_network.MacAddress; - - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "switching to adhoc master\n"); - - memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, - sizeof(struct cfg80211_ssid)); - - rtw_update_registrypriv_dev_network23a(adapter); - rtw_generate_random_ibss23a(ibss); - - pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE; - - ret = rtw_createbss_cmd23a(adapter); - if (ret != _SUCCESS) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Error =>rtw_createbss_cmd23a status FAIL\n"); - } else { - pmlmepriv->to_join = false; - } - - return ret; -} - -int rtw_do_join_network(struct rtw_adapter *adapter, - struct wlan_network *candidate) -{ - int ret; - - /* check for situation of _FW_LINKED */ - if (check_fwstate(&adapter->mlmepriv, _FW_LINKED)) { - DBG_8723A("%s: _FW_LINKED while ask_for_joinbss!\n", __func__); - - rtw_disassoc_cmd23a(adapter, 0, true); - rtw_indicate_disconnect23a(adapter); - rtw_free_assoc_resources23a(adapter, 0); - } - set_fwstate(&adapter->mlmepriv, _FW_UNDER_LINKING); - - ret = rtw_joinbss_cmd23a(adapter, candidate); - - if (ret == _SUCCESS) - mod_timer(&adapter->mlmepriv.assoc_timer, - jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT)); - - return ret; -} - -int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv) -{ - struct rtw_adapter *adapter; - struct wlan_network *candidate = NULL; - int ret; - - adapter = pmlmepriv->nic_hdl; - - candidate = rtw_select_candidate_from_queue(pmlmepriv); - if (!candidate) { - DBG_8723A("%s: return _FAIL(candidate == NULL)\n", __func__); - ret = _FAIL; - goto exit; - } else { - DBG_8723A("%s: candidate: %s(%pM, ch:%u)\n", - __func__, - candidate->network.Ssid.ssid, - candidate->network.MacAddress, - candidate->network.DSConfig); - } - - ret = rtw_do_join_network(adapter, candidate); - -exit: - return ret; -} - -int rtw_set_auth23a(struct rtw_adapter *adapter, - struct security_priv *psecuritypriv) -{ - struct cmd_obj *pcmd; - struct setauth_parm *psetauthparm; - struct cmd_priv *pcmdpriv = &adapter->cmdpriv; - int res = _SUCCESS; - - pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!pcmd) { - res = _FAIL; /* try again */ - goto exit; - } - - psetauthparm = kzalloc(sizeof(struct setauth_parm), GFP_KERNEL); - if (!psetauthparm) { - kfree(pcmd); - res = _FAIL; - goto exit; - } - - psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm; - - pcmd->cmdcode = _SetAuth_CMD_; - pcmd->parmbuf = (unsigned char *)psetauthparm; - pcmd->cmdsz = (sizeof(struct setauth_parm)); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "after enqueue set_auth_cmd, auth_mode=%x\n", - psecuritypriv->dot11AuthAlgrthm); - - res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); - -exit: - - return res; -} - -int rtw_set_key23a(struct rtw_adapter *adapter, - struct security_priv *psecuritypriv, int keyid, u8 set_tx) -{ - u8 keylen; - struct cmd_obj *pcmd; - struct setkey_parm *psetkeyparm; - struct cmd_priv *pcmdpriv = &adapter->cmdpriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - int res = _SUCCESS; - - if (keyid >= 4) { - res = _FAIL; - goto exit; - } - - pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!pcmd) { - res = _FAIL; /* try again */ - goto exit; - } - psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL); - if (!psetkeyparm) { - kfree(pcmd); - res = _FAIL; - goto exit; - } - - if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { - psetkeyparm->algorithm = (unsigned char) - psecuritypriv->dot118021XGrpPrivacy; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_set_key23a: psetkeyparm->algorithm = (unsigned char)psecuritypriv->dot118021XGrpPrivacy =%d\n", - psetkeyparm->algorithm); - } else { - psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_set_key23a: psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm =%d\n", - psetkeyparm->algorithm); - } - psetkeyparm->keyid = keyid;/* 0~3 */ - psetkeyparm->set_tx = set_tx; - if (is_wep_enc(psetkeyparm->algorithm)) - pmlmepriv->key_mask |= BIT(psetkeyparm->keyid); - - DBG_8723A("==> rtw_set_key23a algorithm(%x), keyid(%x), key_mask(%x)\n", - psetkeyparm->algorithm, psetkeyparm->keyid, - pmlmepriv->key_mask); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_set_key23a: psetkeyparm->algorithm =%d psetkeyparm->keyid = (u8)keyid =%d\n", - psetkeyparm->algorithm, keyid); - - switch (psetkeyparm->algorithm) { - case WLAN_CIPHER_SUITE_WEP40: - keylen = 5; - memcpy(&psetkeyparm->key[0], - &psecuritypriv->wep_key[keyid].key, keylen); - break; - case WLAN_CIPHER_SUITE_WEP104: - keylen = 13; - memcpy(&psetkeyparm->key[0], - &psecuritypriv->wep_key[keyid].key, keylen); - break; - case WLAN_CIPHER_SUITE_TKIP: - keylen = 16; - memcpy(&psetkeyparm->key, - &psecuritypriv->dot118021XGrpKey[keyid], keylen); - psetkeyparm->grpkey = 1; - break; - case WLAN_CIPHER_SUITE_CCMP: - keylen = 16; - memcpy(&psetkeyparm->key, - &psecuritypriv->dot118021XGrpKey[keyid], keylen); - psetkeyparm->grpkey = 1; - break; - default: - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "rtw_set_key23a:psecuritypriv->dot11PrivacyAlgrthm = %x (must be 1 or 2 or 4 or 5)\n", - psecuritypriv->dot11PrivacyAlgrthm); - res = _FAIL; - kfree(pcmd); - kfree(psetkeyparm); - goto exit; - } - - pcmd->cmdcode = _SetKey_CMD_; - pcmd->parmbuf = (u8 *)psetkeyparm; - pcmd->cmdsz = (sizeof(struct setkey_parm)); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - /* sema_init(&pcmd->cmd_sem, 0); */ - - res = rtw_enqueue_cmd23a(pcmdpriv, pcmd); - -exit: - - return res; -} - -/* adjust IEs for rtw_joinbss_cmd23a in WMM */ -int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie, - u8 *out_ie, uint in_len, uint initial_out_len) -{ - int ielength; - const u8 *p; - - ielength = initial_out_len; - - p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WMM, - in_ie, in_len); - - if (p && p[1]) { - memcpy(out_ie + initial_out_len, p, 9); - - out_ie[initial_out_len + 1] = 7; - out_ie[initial_out_len + 6] = 0; - out_ie[initial_out_len + 8] = 0; - - ielength += 9; - } - - return ielength; -} - -/* */ -/* Ported from 8185: IsInPreAuthKeyList(). - (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.) */ -/* Added by Annie, 2006-05-07. */ -/* */ -/* Search by BSSID, */ -/* Return Value: */ -/* -1 :if there is no pre-auth key in the table */ -/* >= 0 :if there is pre-auth key, and return the entry id */ -/* */ -/* */ - -static int SecIsInPMKIDList(struct rtw_adapter *Adapter, u8 *bssid) -{ - struct security_priv *psecuritypriv = &Adapter->securitypriv; - int i = 0; - - do { - if (psecuritypriv->PMKIDList[i].bUsed && - ether_addr_equal(psecuritypriv->PMKIDList[i].Bssid, bssid)) { - break; - } else { - i++; - /* continue; */ - } - } while (i < NUM_PMKID_CACHE); - - if (i == NUM_PMKID_CACHE) - i = -1;/* Could not find. */ - else { - /* There is one Pre-Authentication Key for - the specific BSSID. */ - } - - return i; -} - -/* */ -/* Check the RSN IE length */ -/* If the RSN IE length <= 20, the RSN IE didn't include - the PMKID information */ -/* 0-11th element in the array are the fixed IE */ -/* 12th element in the array is the IE */ -/* 13th element in the array is the IE length */ -/* */ - -static int rtw_append_pmkid(struct rtw_adapter *Adapter, int iEntry, - u8 *ie, uint ie_len) -{ - struct security_priv *psecuritypriv = &Adapter->securitypriv; - - if (ie[1] <= 20) { - /* The RSN IE didn't include the PMK ID, - append the PMK information */ - ie[ie_len] = 1; - ie_len++; - ie[ie_len] = 0; /* PMKID count = 0x0100 */ - ie_len++; - memcpy(&ie[ie_len], - &psecuritypriv->PMKIDList[iEntry].PMKID, 16); - - ie_len += 16; - ie[1] += 18;/* PMKID length = 2+16 */ - } - return ie_len; -} - -int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie, - uint in_len) -{ - u8 authmode; - uint ielength; - int iEntry; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct security_priv *psecuritypriv = &adapter->securitypriv; - uint ndisauthmode = psecuritypriv->ndisauthtype; - uint ndissecuritytype = psecuritypriv->ndisencryptstatus; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - "+rtw_restruct_sec_ie23a: ndisauthmode=%d ndissecuritytype=%d\n", - ndisauthmode, ndissecuritytype); - - ielength = 0; - if (ndisauthmode == Ndis802_11AuthModeWPA || - ndisauthmode == Ndis802_11AuthModeWPAPSK) - authmode = WLAN_EID_VENDOR_SPECIFIC; - if (ndisauthmode == Ndis802_11AuthModeWPA2 || - ndisauthmode == Ndis802_11AuthModeWPA2PSK) - authmode = WLAN_EID_RSN; - - if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) { - memcpy(out_ie + ielength, psecuritypriv->wps_ie, - psecuritypriv->wps_ie_len); - - ielength += psecuritypriv->wps_ie_len; - } else if (authmode == WLAN_EID_VENDOR_SPECIFIC || - authmode == WLAN_EID_RSN) { - /* copy RSN or SSN */ - memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0], - psecuritypriv->supplicant_ie[1] + 2); - ielength += psecuritypriv->supplicant_ie[1] + 2; - } - - iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid); - if (iEntry < 0) - return ielength; - else { - if (authmode == WLAN_EID_RSN) - ielength = rtw_append_pmkid(adapter, iEntry, - out_ie, ielength); - } - - return ielength; -} - -void rtw_init_registrypriv_dev_network23a(struct rtw_adapter *adapter) -{ - struct registry_priv *pregistrypriv = &adapter->registrypriv; - struct eeprom_priv *peepriv = &adapter->eeprompriv; - struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; - u8 *myhwaddr = myid(peepriv); - - ether_addr_copy(pdev_network->MacAddress, myhwaddr); - - memcpy(&pdev_network->Ssid, &pregistrypriv->ssid, - sizeof(struct cfg80211_ssid)); - - pdev_network->beacon_interval = 100; -} - -void rtw_update_registrypriv_dev_network23a(struct rtw_adapter *adapter) -{ - int sz = 0; - struct registry_priv *pregistrypriv = &adapter->registrypriv; - struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; - struct security_priv *psecuritypriv = &adapter->securitypriv; - struct wlan_network *cur_network = &adapter->mlmepriv.cur_network; - /* struct xmit_priv *pxmitpriv = &adapter->xmitpriv; */ - - pdev_network->Privacy = - (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0); - - pdev_network->Rssi = 0; - - pdev_network->DSConfig = pregistrypriv->channel; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "pregistrypriv->channel =%d, pdev_network->DSConfig = 0x%x\n", - pregistrypriv->channel, pdev_network->DSConfig); - - if (cur_network->network.ifmode == NL80211_IFTYPE_ADHOC) - pdev_network->ATIMWindow = 0; - - pdev_network->ifmode = cur_network->network.ifmode; - - /* 1. Supported rates */ - /* 2. IE */ - - sz = rtw_generate_ie23a(pregistrypriv); - - pdev_network->IELength = sz; - - pdev_network->Length = - get_wlan_bssid_ex_sz(pdev_network); - - /* notes: translate IELength & Length after assign the - Length to cmdsz in createbss_cmd(); */ - /* pdev_network->IELength = cpu_to_le32(sz); */ -} - -/* the function is at passive_level */ -void rtw_joinbss_reset23a(struct rtw_adapter *padapter) -{ - u8 threshold; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - /* todo: if you want to do something io/reg/hw setting - before join_bss, please add code here */ - - pmlmepriv->num_FortyMHzIntolerant = 0; - - pmlmepriv->num_sta_no_ht = 0; - - phtpriv->ampdu_enable = false;/* reset to disabled */ - - /* TH = 1 => means that invalidate usb rx aggregation */ - /* TH = 0 => means that validate usb rx aggregation, use init value. */ - if (phtpriv->ht_option) { - if (padapter->registrypriv.wifi_spec == 1) - threshold = 1; - else - threshold = 0; - } else - threshold = 1; - - rtl8723a_set_rxdma_agg_pg_th(padapter, threshold); -} - -/* the function is >= passive_level */ -bool rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie, - u8 *out_ie, uint in_len, uint *pout_len) -{ - u32 out_len; - int max_rx_ampdu_factor; - unsigned char *pframe; - const u8 *p; - struct ieee80211_ht_cap ht_capie; - u8 WMM_IE[7] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - phtpriv->ht_option = false; - - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, in_ie, in_len); - - if (p && p[1] > 0) { - u32 rx_packet_offset, max_recvbuf_sz; - - if (pmlmepriv->qos_option == 0) { - out_len = *pout_len; - pframe = rtw_set_ie23a(out_ie + out_len, - WLAN_EID_VENDOR_SPECIFIC, - sizeof(WMM_IE), WMM_IE, - pout_len); - - pmlmepriv->qos_option = 1; - } - - out_len = *pout_len; - - memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap)); - - ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_TX_STBC | IEEE80211_HT_CAP_DSSSCCK40); - - GetHalDefVar8192CUsb(padapter, HAL_DEF_RX_PACKET_OFFSET, - &rx_packet_offset); - GetHalDefVar8192CUsb(padapter, HAL_DEF_MAX_RECVBUF_SZ, - &max_recvbuf_sz); - - GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, - &max_rx_ampdu_factor); - ht_capie.ampdu_params_info = max_rx_ampdu_factor & 0x03; - - if (padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) - ht_capie.ampdu_params_info |= - (IEEE80211_HT_AMPDU_PARM_DENSITY& (0x07 << 2)); - else - ht_capie.ampdu_params_info |= - (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00); - - pframe = rtw_set_ie23a(out_ie + out_len, WLAN_EID_HT_CAPABILITY, - sizeof(struct ieee80211_ht_cap), - (unsigned char *)&ht_capie, pout_len); - - phtpriv->ht_option = true; - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, in_ie, in_len); - if (p && (p[1] == sizeof(struct ieee80211_ht_operation))) { - out_len = *pout_len; - pframe = rtw_set_ie23a(out_ie + out_len, - WLAN_EID_HT_OPERATION, - p[1], p + 2 , pout_len); - } - } - - return phtpriv->ht_option; -} - -/* the function is > passive_level (in critical_section) */ -void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len) -{ - u8 max_ampdu_sz; - const u8 *p; - struct ieee80211_ht_cap *pht_capie; - struct ieee80211_ht_operation *pht_addtinfo; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (!phtpriv->ht_option) - return; - - if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable)) - return; - - DBG_8723A("+rtw_update_ht_cap23a()\n"); - - /* maybe needs check if ap supports rx ampdu. */ - if (!phtpriv->ampdu_enable && pregistrypriv->ampdu_enable == 1) { - if (pregistrypriv->wifi_spec == 1) - phtpriv->ampdu_enable = false; - else - phtpriv->ampdu_enable = true; - } else if (pregistrypriv->ampdu_enable == 2) - phtpriv->ampdu_enable = true; - - /* check Max Rx A-MPDU Size */ - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, ie_len); - - if (p && p[1] > 0) { - pht_capie = (struct ieee80211_ht_cap *)(p + 2); - max_ampdu_sz = pht_capie->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR; - /* max_ampdu_sz (kbytes); */ - max_ampdu_sz = 1 << (max_ampdu_sz + 3); - - phtpriv->rx_ampdu_maxlen = max_ampdu_sz; - } - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, pie, ie_len); - if (p && p[1] > 0) { - pht_addtinfo = (struct ieee80211_ht_operation *)(p + 2); - /* todo: */ - } - - /* update cur_bwmode & cur_ch_offset */ - if (pregistrypriv->cbw40_enable && - pmlmeinfo->ht_cap.cap_info & - cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40) && - pmlmeinfo->HT_info.ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) { - int i; - u8 rf_type; - - rf_type = rtl8723a_get_rf_type(padapter); - - /* update the MCS rates */ - for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { - if (rf_type == RF_1T1R || rf_type == RF_1T2R) - pmlmeinfo->ht_cap.mcs.rx_mask[i] &= - MCS_rate_1R23A[i]; - else - pmlmeinfo->ht_cap.mcs.rx_mask[i] &= - MCS_rate_2R23A[i]; - } - /* switch to the 40M Hz mode according to the AP */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40; - switch (pmlmeinfo->HT_info.ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - break; - - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - break; - - default: - pmlmeext->cur_ch_offset = - HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - } - - /* */ - /* Config SM Power Save setting */ - /* */ - pmlmeinfo->SM_PS = - (le16_to_cpu(pmlmeinfo->ht_cap.cap_info) & - IEEE80211_HT_CAP_SM_PS) >> IEEE80211_HT_CAP_SM_PS_SHIFT; - if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) - DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__); - - /* */ - /* Config current HT Protection mode. */ - /* */ - pmlmeinfo->HT_protection = - le16_to_cpu(pmlmeinfo->HT_info.operation_mode) & - IEEE80211_HT_OP_MODE_PROTECTION; -} - -void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - u8 issued; - int priority; - struct sta_info *psta; - struct ht_priv *phtpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - s32 bmcst = is_multicast_ether_addr(pattrib->ra); - - if (bmcst || padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100) - return; - - priority = pattrib->priority; - - if (pattrib->psta) - psta = pattrib->psta; - else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra); - } - - if (!psta) { - DBG_8723A("%s, psta == NUL\n", __func__); - return; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", - __func__, psta->state); - return; - } - - phtpriv = &psta->htpriv; - - if (phtpriv->ht_option && phtpriv->ampdu_enable) { - issued = (phtpriv->agg_enable_bitmap>>priority)&0x1; - issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1; - - if (issued == 0) { - DBG_8723A("rtw_issue_addbareq_cmd23a, p =%d\n", - priority); - psta->htpriv.candidate_tid_bitmap |= BIT(priority); - rtw_addbareq_cmd23a(padapter, (u8) priority, - pattrib->ra); - } - } -} - -int rtw_linked_check(struct rtw_adapter *padapter) -{ - if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) || - check_fwstate(&padapter->mlmepriv, - WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) { - if (padapter->stapriv.asoc_sta_count > 2) - return true; - } else { /* Station mode */ - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) - return true; - } - return false; -} diff --git a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c deleted file mode 100644 index 7dd1540ebedd..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c +++ /dev/null @@ -1,6187 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_MLME_EXT_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <wifi.h> -#include <rtw_mlme_ext.h> -#include <wlan_bssdef.h> -#include <mlme_osdep.h> -#include <recv_osdep.h> -#include <linux/ieee80211.h> -#include <rtl8723a_hal.h> - -static int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int DoReserved23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); - -static int on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int on_action_public23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static int OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame); - -static void issue_assocreq(struct rtw_adapter *padapter); -static void issue_probereq(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, u8 *da); -static int issue_probereq_ex(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, - u8 *da, int try_cnt, int wait_ms); -static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da); -static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta, - unsigned short status); -static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da, - unsigned short reason, int try_cnt, int wait_ms); -static void start_clnt_assoc(struct rtw_adapter *padapter); -static void start_clnt_auth(struct rtw_adapter *padapter); -static void start_clnt_join(struct rtw_adapter *padapter); -static void start_create_ibss(struct rtw_adapter *padapter); -static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); - -#ifdef CONFIG_8723AU_AP_MODE -static int OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame); -static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status, - struct sta_info *pstat, u16 pkt_type); -#endif - -static struct mlme_handler mlme_sta_tbl[]={ - {"OnAssocReq23a", &OnAssocReq23a}, - {"OnAssocRsp23a", &OnAssocRsp23a}, - {"OnReAssocReq", &OnAssocReq23a}, - {"OnReAssocRsp", &OnAssocRsp23a}, - {"OnProbeReq23a", &OnProbeReq23a}, - {"OnProbeRsp23a", &OnProbeRsp23a}, - - /*---------------------------------------------------------- - below 2 are reserved - -----------------------------------------------------------*/ - {"DoReserved23a", &DoReserved23a}, - {"DoReserved23a", &DoReserved23a}, - {"OnBeacon23a", &OnBeacon23a}, - {"OnATIM", &OnAtim23a}, - {"OnDisassoc23a", &OnDisassoc23a}, - {"OnAuth23a", &OnAuth23aClient23a}, - {"OnDeAuth23a", &OnDeAuth23a}, - {"OnAction23a", &OnAction23a}, -}; - -static struct action_handler OnAction23a_tbl[]={ - {WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct23a}, - {WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction23a_qos}, - {WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction23a_dls}, - {WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction23a_back23a}, - {WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public23a}, - {WLAN_CATEGORY_HT, "ACTION_HT", &OnAction23a_ht}, - {WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved23a}, - {WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction23a_wmm}, - {WLAN_CATEGORY_VENDOR_SPECIFIC, "ACTION_P2P", &OnAction23a_p2p}, -}; - -static u8 null_addr[ETH_ALEN]= {0, 0, 0, 0, 0, 0}; - -/************************************************** -OUI definitions for the vendor specific IE -***************************************************/ -unsigned char WMM_OUI23A[] = {0x00, 0x50, 0xf2, 0x02}; -unsigned char WPS_OUI23A[] = {0x00, 0x50, 0xf2, 0x04}; -unsigned char P2P_OUI23A[] = {0x50, 0x6F, 0x9A, 0x09}; -unsigned char WFD_OUI23A[] = {0x50, 0x6F, 0x9A, 0x0A}; - -unsigned char WMM_INFO_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; -unsigned char WMM_PARA_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; - -static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20}; - -/******************************************************** -MCS rate definitions -*********************************************************/ -unsigned char MCS_rate_2R23A[16] = { - 0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; -unsigned char MCS_rate_1R23A[16] = { - 0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; - -/******************************************************** -ChannelPlan definitions -*********************************************************/ - -static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = { - /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, - /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, - /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, - /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, - /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */ - {{10, 11, 12, 13}, 4}, - /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */ - {{}, 0}, -}; - -static struct rt_channel_plan_5g RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = { - /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */ - {{}, 0}, - /* 0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 128, 132, 136, 140}, 19}, - /* 0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, - /* 0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22}, - /* 0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, - /* 0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */ - {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, - /* 0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, - /* 0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12}, - /* 0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */ - {{149, 153, 157, 161, 165}, 5}, - /* 0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */ - {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, - /* 0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 136, 140, 149, 153, 157, 161, 165}, 20}, - /* 0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 149, 153, 157, 161, 165}, 20}, - /* 0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 120, 124, 128, 132, 136, 140}, 19}, - /* 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */ - {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, - /* 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */ - {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, - /* 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */ - {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, - 153, 157, 161, 165}, 15}, - /* 0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */ - {{56, 60, 64, 149, 153, 157, 161, 165}, 8}, - - /* Driver self defined for old channel plan Compatible, - Remember to modify if have new channel plan definition ===== */ - /* 0x11, RT_CHANNEL_DOMAIN_5G_FCC */ - {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, - 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21}, - /* 0x12, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */ - {{36, 40, 44, 48}, 4}, - /* 0x13, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */ - {{36, 40, 44, 48, 149, 153, 157, 161}, 8}, -}; - -static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { - /* 0x00 ~ 0x1F , Old Define ===== */ - {0x02, 0x11}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */ - {0x02, 0x0A}, /* 0x01, RT_CHANNEL_DOMAIN_IC */ - {0x01, 0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */ - {0x01, 0x00}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */ - {0x01, 0x00}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */ - {0x03, 0x00}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */ - {0x03, 0x00}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */ - {0x01, 0x09}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */ - {0x03, 0x09}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */ - {0x03, 0x00}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */ - {0x00, 0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */ - {0x02, 0x0F}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */ - {0x01, 0x08}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */ - {0x02, 0x06}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */ - {0x02, 0x0B}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */ - {0x02, 0x09}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */ - {0x01, 0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */ - {0x02, 0x05}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */ - {0x01, 0x12}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ - {0x00, 0x04}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */ - {0x02, 0x10}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */ - {0x00, 0x12}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */ - {0x00, 0x13}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */ - {0x03, 0x12}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ - {0x05, 0x08}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */ - {0x02, 0x08}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */ - {0x00, 0x00}, /* 0x1A, */ - {0x00, 0x00}, /* 0x1B, */ - {0x00, 0x00}, /* 0x1C, */ - {0x00, 0x00}, /* 0x1D, */ - {0x00, 0x00}, /* 0x1E, */ - {0x05, 0x04}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */ - /* 0x20 ~ 0x7F , New Define ===== */ - {0x00, 0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */ - {0x01, 0x00}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */ - {0x02, 0x00}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */ - {0x03, 0x00}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */ - {0x04, 0x00}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */ - {0x02, 0x04}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */ - {0x00, 0x01}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */ - {0x03, 0x0C}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */ - {0x00, 0x0B}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */ - {0x00, 0x05}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */ - {0x00, 0x00}, /* 0x2A, */ - {0x00, 0x00}, /* 0x2B, */ - {0x00, 0x00}, /* 0x2C, */ - {0x00, 0x00}, /* 0x2D, */ - {0x00, 0x00}, /* 0x2E, */ - {0x00, 0x00}, /* 0x2F, */ - {0x00, 0x06}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */ - {0x00, 0x07}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */ - {0x00, 0x08}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */ - {0x00, 0x09}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */ - {0x02, 0x0A}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */ - {0x00, 0x02}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */ - {0x00, 0x03}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */ - {0x03, 0x0D}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */ - {0x03, 0x0E}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */ - {0x02, 0x0F}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */ - {0x00, 0x00}, /* 0x3A, */ - {0x00, 0x00}, /* 0x3B, */ - {0x00, 0x00}, /* 0x3C, */ - {0x00, 0x00}, /* 0x3D, */ - {0x00, 0x00}, /* 0x3E, */ - {0x00, 0x00}, /* 0x3F, */ - {0x02, 0x10}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */ - {0x03, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */ -}; - -static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = -{0x03, 0x02}; /* use the conbination for max channel numbers */ - -static void dummy_event_callback(struct rtw_adapter *adapter, const u8 *pbuf) -{ -} - -static struct fwevent wlanevents[] = -{ - {0, &dummy_event_callback}, /*0*/ - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, &rtw_survey_event_cb23a}, /*8*/ - {sizeof (struct surveydone_event), &rtw_surveydone_event_callback23a}, - {0, &rtw23a_joinbss_event_cb}, /*10*/ - {sizeof(struct stassoc_event), &rtw_stassoc_event_callback23a}, - {sizeof(struct stadel_event), &rtw_stadel_event_callback23a}, - {0, &dummy_event_callback}, - {0, &dummy_event_callback}, - {0, NULL}, /*15*/ - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, &dummy_event_callback}, - {0, NULL}, /*20*/ - {0, NULL}, - {0, NULL}, - {0, &dummy_event_callback}, - {0, NULL}, -}; - - -static void rtw_correct_TSF(struct rtw_adapter *padapter) -{ - hw_var_set_correct_tsf(padapter); -} - -static void -rtw_update_TSF(struct mlme_ext_priv *pmlmeext, struct ieee80211_mgmt *mgmt) -{ - pmlmeext->TSFValue = get_unaligned_le64(&mgmt->u.beacon.timestamp); -} - -/* - * Search the @param channel_num in given @param channel_set - * @ch_set: the given channel set - * @ch: the given channel number - * - * return the index of channel_num in channel_set, -1 if not found - */ -int rtw_ch_set_search_ch23a(struct rt_channel_info *ch_set, const u32 ch) -{ - int i; - - for (i = 0; ch_set[i]. ChannelNum != 0; i++) { - if (ch == ch_set[i].ChannelNum) - break; - } - - if (i >= ch_set[i].ChannelNum) - return -1; - return i; -} - -/**************************************************************************** - -Following are the initialization functions for WiFi MLME - -*****************************************************************************/ - -int init_hw_mlme_ext23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - return _SUCCESS; -} - -static void init_mlme_ext_priv23a_value(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - unsigned char mixed_datarate[NumRates] = { - _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, - _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_, - _48M_RATE_, _54M_RATE_, 0xff}; - unsigned char mixed_basicrate[NumRates] = { - _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, - _12M_RATE_, _24M_RATE_, 0xff,}; - - atomic_set(&pmlmeext->event_seq, 0); - /* reset to zero when disconnect at client mode */ - pmlmeext->mgnt_seq = 0; - - pmlmeext->cur_channel = padapter->registrypriv.channel; - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - pmlmeext->retry = 0; - - pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode; - - memcpy(pmlmeext->datarate, mixed_datarate, NumRates); - memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates); - - if (pmlmeext->cur_channel > 14) - pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB; - else - pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; - - pmlmeext->sitesurvey_res.state = SCAN_DISABLE; - pmlmeext->sitesurvey_res.channel_idx = 0; - pmlmeext->sitesurvey_res.bss_cnt = 0; - pmlmeext->scan_abort = false; - - pmlmeinfo->state = MSR_NOLINK; - pmlmeinfo->reauth_count = 0; - pmlmeinfo->reassoc_count = 0; - pmlmeinfo->link_count = 0; - pmlmeinfo->auth_seq = 0; - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; - pmlmeinfo->key_index = 0; - pmlmeinfo->iv = 0; - - pmlmeinfo->enc_algo = 0; - pmlmeinfo->authModeToggle = 0; - - memset(pmlmeinfo->chg_txt, 0, 128); - - pmlmeinfo->slotTime = SHORT_SLOT_TIME; - pmlmeinfo->preamble_mode = PREAMBLE_AUTO; - - pmlmeinfo->dialogToken = 0; - - pmlmeext->action_public_rxseq = 0xffff; - pmlmeext->action_public_dialog_token = 0xff; -} - -static int has_channel(struct rt_channel_info *channel_set, - u8 chanset_size, u8 chan) { - int i; - - for (i = 0; i < chanset_size; i++) { - if (channel_set[i].ChannelNum == chan) - return 1; - } - - return 0; -} - -static void init_channel_list(struct rtw_adapter *padapter, - struct rt_channel_info *channel_set, - u8 chanset_size, - struct p2p_channels *channel_list) -{ - struct p2p_oper_class_map op_class[] = { - { IEEE80211G, 81, 1, 13, 1, BW20 }, - { IEEE80211G, 82, 14, 14, 1, BW20 }, - { IEEE80211A, 115, 36, 48, 4, BW20 }, - { IEEE80211A, 116, 36, 44, 8, BW40PLUS }, - { IEEE80211A, 117, 40, 48, 8, BW40MINUS }, - { IEEE80211A, 124, 149, 161, 4, BW20 }, - { IEEE80211A, 125, 149, 169, 4, BW20 }, - { IEEE80211A, 126, 149, 157, 8, BW40PLUS }, - { IEEE80211A, 127, 153, 161, 8, BW40MINUS }, - { -1, 0, 0, 0, 0, BW20 } - }; - - int cla, op; - - cla = 0; - - for (op = 0; op_class[op].op_class; op++) { - u8 ch; - struct p2p_oper_class_map *o = &op_class[op]; - struct p2p_reg_class *reg = NULL; - - for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { - if (!has_channel(channel_set, chanset_size, ch)) - continue; - - if ((0 == padapter->registrypriv.ht_enable) && - (o->inc == 8)) - continue; - - if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) && - ((BW40MINUS == o->bw) || (BW40PLUS == o->bw))) - continue; - - if (reg == NULL) { - reg = &channel_list->reg_class[cla]; - cla++; - reg->reg_class = o->op_class; - reg->channels = 0; - } - reg->channel[reg->channels] = ch; - reg->channels++; - } - } - channel_list->reg_classes = cla; -} - -static u8 init_channel_set(struct rtw_adapter *padapter, u8 cplan, - struct rt_channel_info *c_set) -{ - u8 i, ch_size = 0; - u8 b5GBand = false, b2_4GBand = false; - u8 Index2G = 0, Index5G = 0; - - memset(c_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM); - - if (cplan >= RT_CHANNEL_DOMAIN_MAX && - cplan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) { - DBG_8723A("ChannelPlan ID %x error !!!!!\n", cplan); - return ch_size; - } - - if (padapter->registrypriv.wireless_mode & WIRELESS_11G) { - b2_4GBand = true; - if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan) - Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G; - else - Index2G = RTW_ChannelPlanMap[cplan].Index2G; - } - - if (padapter->registrypriv.wireless_mode & WIRELESS_11A) { - b5GBand = true; - if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan) - Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G; - else - Index5G = RTW_ChannelPlanMap[cplan].Index5G; - } - - if (b2_4GBand) { - for (i = 0; i < RTW_ChannelPlan2G[Index2G].Len; i++) { - c_set[ch_size].ChannelNum = - RTW_ChannelPlan2G[Index2G].Channel[i]; - - if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == cplan) || - /* Channel 1~11 is active, and 12~14 is passive */ - RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == cplan) { - if (c_set[ch_size].ChannelNum >= 1 && - c_set[ch_size].ChannelNum <= 11) - c_set[ch_size].ScanType = SCAN_ACTIVE; - else if (c_set[ch_size].ChannelNum >= 12 && - c_set[ch_size].ChannelNum <= 14) - c_set[ch_size].ScanType = SCAN_PASSIVE; - } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == cplan || - RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan || - RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) { - /* channel 12~13, passive scan */ - if (c_set[ch_size].ChannelNum <= 11) - c_set[ch_size].ScanType = SCAN_ACTIVE; - else - c_set[ch_size].ScanType = SCAN_PASSIVE; - } else - c_set[ch_size].ScanType = SCAN_ACTIVE; - - ch_size++; - } - } - - if (b5GBand) { - for (i = 0; i < RTW_ChannelPlan5G[Index5G].Len; i++) { - if (RTW_ChannelPlan5G[Index5G].Channel[i] <= 48 || - RTW_ChannelPlan5G[Index5G].Channel[i] >= 149) { - c_set[ch_size].ChannelNum = - RTW_ChannelPlan5G[Index5G].Channel[i]; - if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan) { - /* passive scan for all 5G channels */ - c_set[ch_size].ScanType = - SCAN_PASSIVE; - } else - c_set[ch_size].ScanType = - SCAN_ACTIVE; - DBG_8723A("%s(): channel_set[%d].ChannelNum = " - "%d\n", __func__, ch_size, - c_set[ch_size].ChannelNum); - ch_size++; - } - } - } - - return ch_size; -} - -int init_mlme_ext_priv23a(struct rtw_adapter *padapter) -{ - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pmlmeext->padapter = padapter; - - init_mlme_ext_priv23a_value(padapter); - pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq; - - init_mlme_ext_timer23a(padapter); - -#ifdef CONFIG_8723AU_AP_MODE - init_mlme_ap_info23a(padapter); -#endif - - pmlmeext->max_chan_nums = init_channel_set(padapter, - pmlmepriv->ChannelPlan, - pmlmeext->channel_set); - init_channel_list(padapter, pmlmeext->channel_set, - pmlmeext->max_chan_nums, &pmlmeext->channel_list); - - pmlmeext->chan_scan_time = SURVEY_TO; - pmlmeext->mlmeext_init = true; - - pmlmeext->active_keep_alive_check = true; - return _SUCCESS; -} - -void free_mlme_ext_priv23a (struct mlme_ext_priv *pmlmeext) -{ - struct rtw_adapter *padapter = pmlmeext->padapter; - - if (!padapter) - return; - - if (padapter->bDriverStopped == true) { - del_timer_sync(&pmlmeext->survey_timer); - del_timer_sync(&pmlmeext->link_timer); - /* del_timer_sync(&pmlmeext->ADDBA_timer); */ - } -} - -static void -_mgt_dispatcher23a(struct rtw_adapter *padapter, struct mlme_handler *ptable, - struct recv_frame *precv_frame) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - - if (ptable->func) { - /* receive the frames that ra(a1) is my address - or ra(a1) is bc address. */ - if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv))&& - !is_broadcast_ether_addr(hdr->addr1)) - return; - - ptable->func(padapter, precv_frame); - } -} - -void mgt_dispatcher23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct mlme_handler *ptable; -#ifdef CONFIG_8723AU_AP_MODE - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; -#endif /* CONFIG_8723AU_AP_MODE */ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - struct sta_info *psta; - u16 stype; - int index; - - if (!ieee80211_is_mgmt(mgmt->frame_control)) - return; - - /* receive the frames that ra(a1) is my address or ra(a1) is - bc address. */ - if (!ether_addr_equal(mgmt->da, myid(&padapter->eeprompriv)) && - !is_broadcast_ether_addr(mgmt->da)) - return; - - ptable = mlme_sta_tbl; - - stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; - index = stype >> 4; - - if (index > 13) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "Currently we do not support reserved sub-fr-type =%d\n", - index); - return; - } - ptable += index; - - psta = rtw_get_stainfo23a(&padapter->stapriv, mgmt->sa); - - if (psta) { - if (ieee80211_has_retry(mgmt->frame_control)) { - if (precv_frame->attrib.seq_num == - psta->RxMgmtFrameSeqNum) { - /* drop the duplicate management frame */ - DBG_8723A("Drop duplicate management frame " - "with seq_num = %d.\n", - precv_frame->attrib.seq_num); - return; - } - } - psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num; - } - -#ifdef CONFIG_8723AU_AP_MODE - switch (stype) { - case IEEE80211_STYPE_AUTH: - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - ptable->func = &OnAuth23a; - else - ptable->func = &OnAuth23aClient23a; - /* pass through */ - case IEEE80211_STYPE_ASSOC_REQ: - case IEEE80211_STYPE_REASSOC_REQ: - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - case IEEE80211_STYPE_PROBE_REQ: - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - _mgt_dispatcher23a(padapter, ptable, precv_frame); - else - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - case IEEE80211_STYPE_BEACON: - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - case IEEE80211_STYPE_ACTION: - /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) */ - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - default: - _mgt_dispatcher23a(padapter, ptable, precv_frame); - break; - } -#else - _mgt_dispatcher23a(padapter, ptable, precv_frame); -#endif -} - -/**************************************************************************** - -Following are the callback functions for each subtype of the management frames - -*****************************************************************************/ - -static int -OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - const u8 *ie; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur = &pmlmeinfo->network; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - int len = skb->len; - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - return _SUCCESS; - - if (!check_fwstate(pmlmepriv, _FW_LINKED) && - !check_fwstate(pmlmepriv, - WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE)) - return _SUCCESS; - - if (unlikely(!ieee80211_is_probe_req(mgmt->frame_control))) { - printk(KERN_WARNING "%s: Received non probe request frame\n", - __func__); - return _FAIL; - } - - len -= offsetof(struct ieee80211_mgmt, u.probe_req.variable); - - ie = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.probe_req.variable, len); - - /* check (wildcard) SSID */ - if (!ie) - goto out; - - if ((ie[1] && memcmp(ie + 2, cur->Ssid.ssid, cur->Ssid.ssid_len)) || - (ie[1] == 0 && pmlmeinfo->hidden_ssid_mode)) { - return _SUCCESS; - } - - if (check_fwstate(pmlmepriv, _FW_LINKED) && - pmlmepriv->cur_network.join_res) - issue_probersp(padapter, mgmt->sa); - -out: - return _SUCCESS; -} - -static int -OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { - report_survey_event23a(padapter, precv_frame); - return _SUCCESS; - } - - return _SUCCESS; -} - -static int -OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - int cam_idx; - struct sta_info *psta; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - int pkt_len = skb->len; - struct wlan_bssid_ex *pbss; - int ret = _SUCCESS; - u8 *p, *pie; - int pie_len; - u32 ielen = 0; - - pie = mgmt->u.beacon.variable; - pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - p = rtw_get_ie23a(pie, WLAN_EID_EXT_SUPP_RATES, &ielen, pie_len); - if (p && ielen > 0) { - if (p[1 + ielen] == 0x2D && p[2 + ielen] != 0x2D) { - /* Invalid value 0x2D is detected in Extended Supported - * Rates (ESR) IE. Try to fix the IE length to avoid - * failed Beacon parsing. - */ - DBG_8723A("[WIFIDBG] Error in ESR IE is detected in " - "Beacon of BSSID: %pM. Fix the length of " - "ESR IE to avoid failed Beacon parsing.\n", - mgmt->bssid); - p[1] = ielen - 1; - } - } - - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { - report_survey_event23a(padapter, precv_frame); - return _SUCCESS; - } - - if (!ether_addr_equal(mgmt->bssid, - get_my_bssid23a(&pmlmeinfo->network))) - goto out; - - if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { - /* we should update current network before auth, - or some IE is wrong */ - pbss = collect_bss_info(padapter, precv_frame); - if (pbss) { - update_network23a(&pmlmepriv->cur_network.network, pbss, - padapter, true); - rtw_get_bcn_info23a(&pmlmepriv->cur_network); - kfree(pbss); - } - - /* check the vendor of the assoc AP */ - pmlmeinfo->assoc_AP_vendor = - check_assoc_AP23a((u8 *)&mgmt->u.beacon, pkt_len - - offsetof(struct ieee80211_mgmt, u)); - - /* update TSF Value */ - rtw_update_TSF(pmlmeext, mgmt); - - /* start auth */ - start_clnt_auth(padapter); - - return _SUCCESS; - } - - if (((pmlmeinfo->state & 0x03) == MSR_AP) && - (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) { - psta = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (psta) { - ret = rtw_check_bcn_info23a(padapter, mgmt, pkt_len); - if (ret != _SUCCESS) { - DBG_8723A_LEVEL(_drv_always_, "ap has changed, " - "disconnect now\n"); - receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, 65535); - return _SUCCESS; - } - /* update WMM, ERP in the beacon */ - /* todo: the timer is used instead of - the number of the beacon received */ - if ((sta_rx_pkts(psta) & 0xf) == 0) { - /* DBG_8723A("update_bcn_info\n"); */ - update_beacon23a_info(padapter, mgmt, - pkt_len, psta); - } - } - } else if ((pmlmeinfo->state&0x03) == MSR_ADHOC) { - psta = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (psta) { - /* update WMM, ERP in the beacon */ - /* todo: the timer is used instead of the - number of the beacon received */ - if ((sta_rx_pkts(psta) & 0xf) == 0) { - /* DBG_8723A("update_bcn_info\n"); */ - update_beacon23a_info(padapter, mgmt, - pkt_len, psta); - } - } else { - /* allocate a new CAM entry for IBSS station */ - cam_idx = allocate_fw_sta_entry23a(padapter); - if (cam_idx == NUM_STA) - goto out; - - /* get supported rate */ - if (update_sta_support_rate23a(padapter, pie, pie_len, - cam_idx) == _FAIL) { - pmlmeinfo->FW_sta_info[cam_idx].status = 0; - goto out; - } - - /* update TSF Value */ - rtw_update_TSF(pmlmeext, mgmt); - - /* report sta add event */ - report_add_sta_event23a(padapter, mgmt->sa, - cam_idx); - } - } - -out: - - return _SUCCESS; -} - -#ifdef CONFIG_8723AU_AP_MODE -static int -OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - static struct sta_info stat; - struct sta_info *pstat = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - u8 *pframe; - const u8 *p; - unsigned char *sa; - u16 auth_mode, seq, algorithm; - int status, len = skb->len; - - if ((pmlmeinfo->state & 0x03) != MSR_AP) - return _FAIL; - - DBG_8723A("+OnAuth23a\n"); - - sa = mgmt->sa; - - auth_mode = psecuritypriv->dot11AuthAlgrthm; - - pframe = mgmt->u.auth.variable; - len = skb->len - offsetof(struct ieee80211_mgmt, u.auth.variable); - - seq = le16_to_cpu(mgmt->u.auth.auth_transaction); - algorithm = le16_to_cpu(mgmt->u.auth.auth_alg); - - DBG_8723A("auth alg =%x, seq =%X\n", algorithm, seq); - - if (auth_mode == 2 && - psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP40 && - psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP104) - auth_mode = 0; - - /* rx a shared-key auth but shared not enabled, or */ - /* rx a open-system auth but shared-key is enabled */ - if ((algorithm != WLAN_AUTH_OPEN && auth_mode == 0) || - (algorithm == WLAN_AUTH_OPEN && auth_mode == 1)) { - DBG_8723A("auth rejected due to bad alg [alg =%d, auth_mib " - "=%d] %02X%02X%02X%02X%02X%02X\n", - algorithm, auth_mode, - sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); - - status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; - - goto auth_fail; - } - - if (rtw_access_ctrl23a(padapter, sa) == false) { - status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - goto auth_fail; - } - - pstat = rtw_get_stainfo23a(pstapriv, sa); - if (!pstat) { - /* allocate a new one */ - DBG_8723A("going to alloc stainfo for sa =%pM\n", sa); - pstat = rtw_alloc_stainfo23a(pstapriv, sa, GFP_ATOMIC); - if (!pstat) { - DBG_8723A(" Exceed the upper limit of supported " - "clients...\n"); - status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - goto auth_fail; - } - - pstat->state = WIFI_FW_AUTH_NULL; - pstat->auth_seq = 0; - - /* pstat->flags = 0; */ - /* pstat->capability = 0; */ - } else { - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&pstat->asoc_list)) { - list_del_init(&pstat->asoc_list); - pstapriv->asoc_list_cnt--; - if (pstat->expire_to > 0) { - /* TODO: STA re_auth within expire_to */ - } - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - if (seq == 1) { - /* TODO: STA re_auth and auth timeout */ - } - } - - spin_lock_bh(&pstapriv->auth_list_lock); - if (list_empty(&pstat->auth_list)) { - list_add_tail(&pstat->auth_list, &pstapriv->auth_list); - pstapriv->auth_list_cnt++; - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - if (pstat->auth_seq == 0) - pstat->expire_to = pstapriv->auth_to; - - if ((pstat->auth_seq + 1) != seq) { - DBG_8723A("(1)auth rejected because out of seq [rx_seq =%d, " - "exp_seq =%d]!\n", seq, pstat->auth_seq+1); - status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; - goto auth_fail; - } - - if (algorithm == WLAN_AUTH_OPEN && (auth_mode == 0 || auth_mode == 2)) { - if (seq == 1) { - pstat->state &= ~WIFI_FW_AUTH_NULL; - pstat->state |= WIFI_FW_AUTH_SUCCESS; - pstat->expire_to = pstapriv->assoc_to; - pstat->authalg = algorithm; - } else { - DBG_8723A("(2)auth rejected because out of seq " - "[rx_seq =%d, exp_seq =%d]!\n", - seq, pstat->auth_seq+1); - status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; - goto auth_fail; - } - } else { /* shared system or auto authentication */ - if (seq == 1) { - /* prepare for the challenging txt... */ - pstat->state &= ~WIFI_FW_AUTH_NULL; - pstat->state |= WIFI_FW_AUTH_STATE; - pstat->authalg = algorithm; - pstat->auth_seq = 2; - } else if (seq == 3) { - /* checking for challenging txt... */ - DBG_8723A("checking for challenging txt...\n"); - - p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pframe, len); - if (!p || p[1] <= 0) { - DBG_8723A("auth rejected because challenge " - "failure!(1)\n"); - status = WLAN_STATUS_CHALLENGE_FAIL; - goto auth_fail; - } - - if (!memcmp(p + 2, pstat->chg_txt, 128)) { - pstat->state &= ~WIFI_FW_AUTH_STATE; - pstat->state |= WIFI_FW_AUTH_SUCCESS; - /* challenging txt is correct... */ - pstat->expire_to = pstapriv->assoc_to; - } else { - DBG_8723A("auth rejected because challenge " - "failure!\n"); - status = WLAN_STATUS_CHALLENGE_FAIL; - goto auth_fail; - } - } else { - DBG_8723A("(3)auth rejected because out of seq " - "[rx_seq =%d, exp_seq =%d]!\n", - seq, pstat->auth_seq+1); - status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; - goto auth_fail; - } - } - - /* Now, we are going to issue_auth... */ - pstat->auth_seq = seq + 1; - - issue_auth(padapter, pstat, WLAN_STATUS_SUCCESS); - - if (pstat->state & WIFI_FW_AUTH_SUCCESS) - pstat->auth_seq = 0; - - return _SUCCESS; - -auth_fail: - - if (pstat) - rtw_free_stainfo23a(padapter, pstat); - - pstat = &stat; - memset((char *)pstat, '\0', sizeof(stat)); - pstat->auth_seq = 2; - ether_addr_copy(pstat->hwaddr, sa); - - issue_auth(padapter, pstat, (unsigned short)status); - - return _FAIL; -} -#endif - -static int -OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned int seq, status, algthm; - unsigned int go2asoc = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - const u8 *p; - u8 *pie; - int plen = skb->len; - - DBG_8723A("%s\n", __func__); - - /* check A1 matches or not */ - if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da)) - return _SUCCESS; - - if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE)) - return _SUCCESS; - - pie = mgmt->u.auth.variable; - plen -= offsetof(struct ieee80211_mgmt, u.auth.variable); - - algthm = le16_to_cpu(mgmt->u.auth.auth_alg); - seq = le16_to_cpu(mgmt->u.auth.auth_transaction); - status = le16_to_cpu(mgmt->u.auth.status_code); - - if (status) { - DBG_8723A("clnt auth fail, status: %d\n", status); - /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */ - if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; - else - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; - /* pmlmeinfo->reauth_count = 0; */ - } - - set_link_timer(pmlmeext, 1); - goto authclnt_fail; - } - - if (seq == 2) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { - /* legendary shared system */ - p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pie, plen); - - if (!p) { - /* DBG_8723A("marc: no challenge text?\n"); */ - goto authclnt_fail; - } - - memcpy((void *)(pmlmeinfo->chg_txt), p + 2, p[1]); - pmlmeinfo->auth_seq = 3; - issue_auth(padapter, NULL, 0); - set_link_timer(pmlmeext, REAUTH_TO); - - return _SUCCESS; - } else { - /* open system */ - go2asoc = 1; - } - } else if (seq == 4) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) - go2asoc = 1; - else - goto authclnt_fail; - } else { - /* this is also illegal */ - /* DBG_8723A("marc: clnt auth failed due to illegal seq =%x\n", - seq); */ - goto authclnt_fail; - } - - if (go2asoc) { - DBG_8723A_LEVEL(_drv_always_, "auth success, start assoc\n"); - start_clnt_assoc(padapter); - return _SUCCESS; - } - -authclnt_fail: - - /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */ - - return _FAIL; -} - -#ifdef CONFIG_8723AU_AP_MODE -static int rtw_validate_vendor_specific_ies(const u8 *pos, int elen) -{ - unsigned int oui; - - /* first 3 bytes in vendor specific information element are the IEEE - * OUI of the vendor. The following byte is used a vendor specific - * sub-type. */ - if (elen < 4) { - DBG_8723A("short vendor specific information element " - "ignored (len =%i)\n", elen); - return -EINVAL; - } - - oui = RTW_GET_BE24(pos); - switch (oui) { - case WLAN_OUI_MICROSOFT: - /* Microsoft/Wi-Fi information elements are further typed and - * subtyped */ - switch (pos[3]) { - case WLAN_OUI_TYPE_MICROSOFT_WPA: - /* Microsoft OUI (00:50:F2) with OUI Type 1: - * real WPA information element */ - break; - case WLAN_OUI_TYPE_MICROSOFT_WMM: - if (elen < 5) { - DBG_8723A("short WME information element " - "ignored (len =%i)\n", elen); - return -EINVAL; - } - switch (pos[4]) { - case WME_OUI_SUBTYPE_INFORMATION_ELEMENT: - case WME_OUI_SUBTYPE_PARAMETER_ELEMENT: - break; - case WME_OUI_SUBTYPE_TSPEC_ELEMENT: - break; - default: - DBG_8723A("unknown WME information element " - "ignored (subtype =%d len =%i)\n", - pos[4], elen); - return -EINVAL; - } - break; - case WLAN_OUI_TYPE_MICROSOFT_WPS: - /* Wi-Fi Protected Setup (WPS) IE */ - break; - default: - DBG_8723A("Unknown Microsoft information element " - "ignored (type =%d len =%i)\n", - pos[3], elen); - return -EINVAL; - } - break; - - case OUI_BROADCOM: - switch (pos[3]) { - case VENDOR_HT_CAPAB_OUI_TYPE: - break; - default: - DBG_8723A("Unknown Broadcom information element " - "ignored (type =%d len =%i)\n", pos[3], elen); - return -EINVAL; - } - break; - - default: - DBG_8723A("unknown vendor specific information element " - "ignored (vendor OUI %02x:%02x:%02x len =%i)\n", - pos[0], pos[1], pos[2], elen); - return -EINVAL; - } - - return 0; -} - -static int rtw_validate_frame_ies(const u8 *start, uint len) -{ - const u8 *pos = start; - int left = len; - int unknown = 0; - - while (left >= 2) { - u8 id, elen; - - id = *pos++; - elen = *pos++; - left -= 2; - - if (elen > left) { - DBG_8723A("%s: IEEE 802.11 failed (id =%d elen =%d " - "left =%i)\n", __func__, id, elen, left); - return -EINVAL; - } - - switch (id) { - case WLAN_EID_SSID: - case WLAN_EID_SUPP_RATES: - case WLAN_EID_FH_PARAMS: - case WLAN_EID_DS_PARAMS: - case WLAN_EID_CF_PARAMS: - case WLAN_EID_TIM: - case WLAN_EID_IBSS_PARAMS: - case WLAN_EID_CHALLENGE: - case WLAN_EID_ERP_INFO: - case WLAN_EID_EXT_SUPP_RATES: - break; - case WLAN_EID_VENDOR_SPECIFIC: - if (rtw_validate_vendor_specific_ies(pos, elen)) - unknown++; - break; - case WLAN_EID_RSN: - case WLAN_EID_PWR_CAPABILITY: - case WLAN_EID_SUPPORTED_CHANNELS: - case WLAN_EID_MOBILITY_DOMAIN: - case WLAN_EID_FAST_BSS_TRANSITION: - case WLAN_EID_TIMEOUT_INTERVAL: - case WLAN_EID_HT_CAPABILITY: - case WLAN_EID_HT_OPERATION: - default: - unknown++; - DBG_8723A("%s IEEE 802.11 ignored unknown element " - "(id =%d elen =%d)\n", __func__, id, elen); - break; - } - - left -= elen; - pos += elen; - } - - if (left) - return -EINVAL; - - return 0; -} -#endif - -static int -OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ -#ifdef CONFIG_8723AU_AP_MODE - u16 capab_info, listen_interval; - struct sta_info *pstat; - unsigned char reassoc; - int i, wpa_ie_len, left; - unsigned char supportRate[16]; - int supportRateNum; - unsigned short status = WLAN_STATUS_SUCCESS; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur = &pmlmeinfo->network; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - const u8 *pos, *p, *wpa_ie, *wps_ie; - u8 *pframe = skb->data; - uint pkt_len = skb->len; - int r; - - if ((pmlmeinfo->state & 0x03) != MSR_AP) - return _FAIL; - - left = pkt_len - sizeof(struct ieee80211_hdr_3addr); - if (ieee80211_is_assoc_req(mgmt->frame_control)) { - reassoc = 0; - pos = mgmt->u.assoc_req.variable; - left -= offsetof(struct ieee80211_mgmt, u.assoc_req.variable); - } else { /* WIFI_REASSOCREQ */ - reassoc = 1; - pos = mgmt->u.reassoc_req.variable; - left -= offsetof(struct ieee80211_mgmt, u.reassoc_req.variable); - } - - if (left < 0) { - DBG_8723A("handle_assoc(reassoc =%d) - too short payload " - "(len =%lu)\n", reassoc, (unsigned long)pkt_len); - return _FAIL; - } - - pstat = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (!pstat) { - status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA; - goto asoc_class2_error; - } - - /* These two are located at the same offsets whether it's an - * assoc_req or a reassoc_req */ - capab_info = get_unaligned_le16(&mgmt->u.assoc_req.capab_info); - listen_interval = - get_unaligned_le16(&mgmt->u.assoc_req.listen_interval); - - DBG_8723A("%s\n", __func__); - - /* check if this stat has been successfully authenticated/assocated */ - if (!(pstat->state & WIFI_FW_AUTH_SUCCESS)) { - if (!(pstat->state & WIFI_FW_ASSOC_SUCCESS)) { - status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA; - goto asoc_class2_error; - } else { - pstat->state &= (~WIFI_FW_ASSOC_SUCCESS); - pstat->state |= WIFI_FW_ASSOC_STATE; - } - } else { - pstat->state &= (~WIFI_FW_AUTH_SUCCESS); - pstat->state |= WIFI_FW_ASSOC_STATE; - } - - pstat->capability = capab_info; - - /* now parse all ieee802_11 ie to point to elems */ - - if (rtw_validate_frame_ies(pos, left)) { - DBG_8723A("STA %pM sent invalid association request\n", - pstat->hwaddr); - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto OnAssocReq23aFail; - } - - /* now we should check all the fields... */ - /* checking SSID */ - p = cfg80211_find_ie(WLAN_EID_SSID, pos, left); - if (!p || p[1] == 0) { - /* broadcast ssid, however it is not allowed in assocreq */ - DBG_8723A("STA %pM sent invalid association request lacking an SSID\n", - pstat->hwaddr); - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto OnAssocReq23aFail; - } else { - /* check if ssid match */ - if (memcmp(p + 2, cur->Ssid.ssid, cur->Ssid.ssid_len)) - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - - if (p[1] != cur->Ssid.ssid_len) - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - if (status != WLAN_STATUS_SUCCESS) - goto OnAssocReq23aFail; - - /* check if the supported rate is ok */ - p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pos, left); - if (!p) { - DBG_8723A("Rx a sta assoc-req which supported rate is " - "empty!\n"); - /* use our own rate set as statoin used */ - /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */ - /* supportRateNum = AP_BSSRATE_LEN; */ - - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto OnAssocReq23aFail; - } else { - memcpy(supportRate, p + 2, p[1]); - supportRateNum = p[1]; - - p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pos, left); - if (p) { - if (supportRateNum <= sizeof(supportRate)) { - memcpy(supportRate+supportRateNum, p + 2, p[1]); - supportRateNum += p[1]; - } - } - } - - /* todo: mask supportRate between AP & STA -> move to update raid */ - /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */ - - /* update station supportRate */ - pstat->bssratelen = supportRateNum; - memcpy(pstat->bssrateset, supportRate, supportRateNum); - Update23aTblForSoftAP(pstat->bssrateset, pstat->bssratelen); - - /* check RSN/WPA/WPS */ - pstat->dot8021xalg = 0; - pstat->wpa_psk = 0; - pstat->wpa_group_cipher = 0; - pstat->wpa2_group_cipher = 0; - pstat->wpa_pairwise_cipher = 0; - pstat->wpa2_pairwise_cipher = 0; - memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie)); - - wpa_ie = cfg80211_find_ie(WLAN_EID_RSN, pos, left); - if (!wpa_ie) - wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - pos, left); - if (wpa_ie) { - int group_cipher = 0, pairwise_cipher = 0; - - wpa_ie_len = wpa_ie[1]; - if (psecuritypriv->wpa_psk & BIT(1)) { - r = rtw_parse_wpa2_ie23a(wpa_ie, wpa_ie_len + 2, - &group_cipher, - &pairwise_cipher, NULL); - if (r == _SUCCESS) { - pstat->dot8021xalg = 1;/* psk, todo:802.1x */ - pstat->wpa_psk |= BIT(1); - - pstat->wpa2_group_cipher = group_cipher & - psecuritypriv->wpa2_group_cipher; - pstat->wpa2_pairwise_cipher = pairwise_cipher & - psecuritypriv->wpa2_pairwise_cipher; - } else - status = WLAN_STATUS_INVALID_IE; - } else if (psecuritypriv->wpa_psk & BIT(0)) { - r = rtw_parse_wpa_ie23a(wpa_ie, wpa_ie_len + 2, - &group_cipher, &pairwise_cipher, - NULL); - if (r == _SUCCESS) { - pstat->dot8021xalg = 1;/* psk, todo:802.1x */ - pstat->wpa_psk |= BIT(0); - - pstat->wpa_group_cipher = group_cipher & - psecuritypriv->wpa_group_cipher; - pstat->wpa_pairwise_cipher = pairwise_cipher & - psecuritypriv->wpa_pairwise_cipher; - } else - status = WLAN_STATUS_INVALID_IE; - } else { - wpa_ie = NULL; - wpa_ie_len = 0; - } - if (wpa_ie && status == WLAN_STATUS_SUCCESS) { - if (!pstat->wpa_group_cipher) - status = WLAN_STATUS_INVALID_GROUP_CIPHER; - - if (!pstat->wpa_pairwise_cipher) - status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER; - } - } - - if (status != WLAN_STATUS_SUCCESS) - goto OnAssocReq23aFail; - - pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); - - wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - pos, left); - - if (!wpa_ie) { - if (wps_ie) { - DBG_8723A("STA included WPS IE in (Re)Association " - "Request - assume WPS is used\n"); - pstat->flags |= WLAN_STA_WPS; - } else { - DBG_8723A("STA did not include WPA/RSN IE in (Re)" - "Association Request - possible WPS use\n"); - pstat->flags |= WLAN_STA_MAYBE_WPS; - } - } else { - int copy_len; - - if (psecuritypriv->wpa_psk == 0) { - DBG_8723A("STA %pM: WPA/RSN IE in association request, but AP don't support WPA/RSN\n", - pstat->hwaddr); - - status = WLAN_STATUS_INVALID_IE; - - goto OnAssocReq23aFail; - } - - if (wps_ie) { - DBG_8723A("STA included WPS IE in (Re)Association " - "Request - WPS is used\n"); - pstat->flags |= WLAN_STA_WPS; - copy_len = 0; - } else { - copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ? - sizeof(pstat->wpa_ie) : (wpa_ie_len + 2); - } - - if (copy_len > 0) - memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len); - } - - /* check if there is WMM IE & support WWM-PS */ - pstat->flags &= ~WLAN_STA_WME; - pstat->qos_option = 0; - pstat->qos_info = 0; - pstat->has_legacy_ac = true; - pstat->uapsd_vo = 0; - pstat->uapsd_vi = 0; - pstat->uapsd_be = 0; - pstat->uapsd_bk = 0; - if (pmlmepriv->qos_option) { - const u8 *end = pos + left; - - p = pos; - - for (;;) { - left = end - p; - p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WMM, - p, left); - if (p) { - pstat->flags |= WLAN_STA_WME; - - pstat->qos_option = 1; - pstat->qos_info = *(p + 8); - - pstat->max_sp_len = - (pstat->qos_info >> 5) & 0x3; - - if ((pstat->qos_info & 0xf) != 0xf) - pstat->has_legacy_ac = true; - else - pstat->has_legacy_ac = false; - - if (pstat->qos_info & 0xf) { - if (pstat->qos_info & BIT(0)) - pstat->uapsd_vo = BIT(0)|BIT(1); - else - pstat->uapsd_vo = 0; - - if (pstat->qos_info & BIT(1)) - pstat->uapsd_vi = BIT(0)|BIT(1); - else - pstat->uapsd_vi = 0; - - if (pstat->qos_info & BIT(2)) - pstat->uapsd_bk = BIT(0)|BIT(1); - else - pstat->uapsd_bk = 0; - - if (pstat->qos_info & BIT(3)) - pstat->uapsd_be = BIT(0)|BIT(1); - else - pstat->uapsd_be = 0; - - break; - } - } else { - break; - } - p = p + p[1] + 2; - } - } - - /* save HT capabilities in the sta object */ - memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap)); - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pos, left); - - if (p && p[1] >= sizeof(struct ieee80211_ht_cap)) { - pstat->flags |= WLAN_STA_HT; - - pstat->flags |= WLAN_STA_WME; - - memcpy(&pstat->htpriv.ht_cap, p + 2, - sizeof(struct ieee80211_ht_cap)); - } else - pstat->flags &= ~WLAN_STA_HT; - - if (!pmlmepriv->htpriv.ht_option && pstat->flags & WLAN_STA_HT){ - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto OnAssocReq23aFail; - } - - if (pstat->flags & WLAN_STA_HT && - (pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP || - pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) { - DBG_8723A("HT: %pM tried to use TKIP with HT association\n", - pstat->hwaddr); - - /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */ - /* goto OnAssocReq23aFail; */ - } - - pstat->flags |= WLAN_STA_NONERP; - for (i = 0; i < pstat->bssratelen; i++) { - if ((pstat->bssrateset[i] & 0x7f) > 22) { - pstat->flags &= ~WLAN_STA_NONERP; - break; - } - } - - if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - pstat->flags |= WLAN_STA_SHORT_PREAMBLE; - else - pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE; - - if (status != WLAN_STATUS_SUCCESS) - goto OnAssocReq23aFail; - - /* TODO: identify_proprietary_vendor_ie(); */ - /* Realtek proprietary IE */ - /* identify if this is Broadcom sta */ - /* identify if this is ralink sta */ - /* Customer proprietary IE */ - - /* get a unique AID */ - if (pstat->aid > 0) { - DBG_8723A(" old AID %d\n", pstat->aid); - } else { - for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++) - if (pstapriv->sta_aid[pstat->aid - 1] == NULL) - break; - - if (pstat->aid > NUM_STA) - pstat->aid = NUM_STA; - if (pstat->aid > pstapriv->max_num_sta) { - - pstat->aid = 0; - - DBG_8723A(" no room for more AIDs\n"); - - status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - - goto OnAssocReq23aFail; - } else { - pstapriv->sta_aid[pstat->aid - 1] = pstat; - DBG_8723A("allocate new AID = (%d)\n", pstat->aid); - } - } - - pstat->state &= ~WIFI_FW_ASSOC_STATE; - pstat->state |= WIFI_FW_ASSOC_SUCCESS; - - spin_lock_bh(&pstapriv->auth_list_lock); - if (!list_empty(&pstat->auth_list)) { - list_del_init(&pstat->auth_list); - pstapriv->auth_list_cnt--; - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (list_empty(&pstat->asoc_list)) { - pstat->expire_to = pstapriv->expire_to; - list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list); - pstapriv->asoc_list_cnt++; - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - /* now the station is qualified to join our BSS... */ - if (pstat->state & WIFI_FW_ASSOC_SUCCESS && - status == WLAN_STATUS_SUCCESS) { - /* 1 bss_cap_update & sta_info_update23a */ - bss_cap_update_on_sta_join23a(padapter, pstat); - sta_info_update23a(padapter, pstat); - - /* issue assoc rsp before notify station join event. */ - if (ieee80211_is_assoc_req(mgmt->frame_control)) - issue_assocrsp(padapter, status, pstat, - IEEE80211_STYPE_ASSOC_RESP); - else - issue_assocrsp(padapter, status, pstat, - IEEE80211_STYPE_REASSOC_RESP); - - /* 2 - report to upper layer */ - DBG_8723A("indicate_sta_join_event to upper layer - hostapd\n"); - rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len); - - /* 3-(1) report sta add event */ - report_add_sta_event23a(padapter, pstat->hwaddr, pstat->aid); - } - - return _SUCCESS; - -asoc_class2_error: - - issue_deauth23a(padapter, mgmt->sa, status); - return _FAIL; - -OnAssocReq23aFail: - - pstat->aid = 0; - if (ieee80211_is_assoc_req(mgmt->frame_control)) - issue_assocrsp(padapter, status, pstat, - IEEE80211_STYPE_ASSOC_RESP); - else - issue_assocrsp(padapter, status, pstat, - IEEE80211_STYPE_REASSOC_RESP); - -#endif /* CONFIG_8723AU_AP_MODE */ - - return _FAIL; -} - -static int -OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *pmgmt = (struct ieee80211_mgmt *) skb->data; - int res; - unsigned short status; - const u8 *p, *pie; - u8 *pframe = skb->data; - int pkt_len = skb->len; - int pielen; - - DBG_8723A("%s\n", __func__); - - /* check A1 matches or not */ - if (!ether_addr_equal(myid(&padapter->eeprompriv), pmgmt->da)) - return _SUCCESS; - - if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE))) - return _SUCCESS; - - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) - return _SUCCESS; - - del_timer_sync(&pmlmeext->link_timer); - - /* status */ - status = le16_to_cpu(pmgmt->u.assoc_resp.status_code); - if (status > 0) { - DBG_8723A("assoc reject, status code: %d\n", status); - pmlmeinfo->state = MSR_NOLINK; - res = -4; - goto report_assoc_result; - } - - /* get capabilities */ - pmlmeinfo->capability = le16_to_cpu(pmgmt->u.assoc_resp.capab_info); - - /* set slot time */ - pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20; - - /* AID */ - res = pmlmeinfo->aid = le16_to_cpu(pmgmt->u.assoc_resp.aid) & 0x3fff; - - pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); - pielen = pkt_len - - offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); - - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, - pmgmt->u.assoc_resp.variable, pielen); - if (p && p[1]) - HT_caps_handler23a(padapter, p); - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, - pmgmt->u.assoc_resp.variable, pielen); - if (p && p[1]) - HT_info_handler23a(padapter, p); - - p = cfg80211_find_ie(WLAN_EID_ERP_INFO, - pmgmt->u.assoc_resp.variable, pielen); - if (p && p[1]) - ERP_IE_handler23a(padapter, p); - - pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); - while (true) { - p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WMM, - pie, pframe + pkt_len - pie); - if (!p) - break; - - pie = p + p[1] + 2; - /* if this IE is too short, try the next */ - if (p[1] <= 4) - continue; - /* if this IE is WMM params, we found what we wanted */ - if (p[6] == 1) - break; - } - - if (p && p[1]) - WMM_param_handler23a(padapter, p); - - pmlmeinfo->state &= ~WIFI_FW_ASSOC_STATE; - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - - /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */ - UpdateBrateTbl23a(padapter, pmlmeinfo->network.SupportedRates); - -report_assoc_result: - pmlmepriv->assoc_rsp_len = 0; - if (res > 0) { - kfree(pmlmepriv->assoc_rsp); - pmlmepriv->assoc_rsp = kmalloc(pkt_len, GFP_ATOMIC); - if (pmlmepriv->assoc_rsp) { - memcpy(pmlmepriv->assoc_rsp, pframe, pkt_len); - pmlmepriv->assoc_rsp_len = pkt_len; - } - } else - kfree(pmlmepriv->assoc_rsp); - - report_join_res23a(padapter, res); - - return _SUCCESS; -} - -static int -OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned short reason; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - - if (!ether_addr_equal(mgmt->bssid, - get_my_bssid23a(&pmlmeinfo->network))) - return _SUCCESS; - - reason = le16_to_cpu(mgmt->u.deauth.reason_code); - - DBG_8723A("%s Reason code(%d)\n", __func__, reason); - -#ifdef CONFIG_8723AU_AP_MODE - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - DBG_8723A_LEVEL(_drv_always_, "ap recv deauth reason code(%d) " - "sta:%pM\n", reason, mgmt->sa); - - psta = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (psta) { - u8 updated = 0; - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&psta->asoc_list)) { - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta23a(padapter, psta, - false, reason); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - associated_clients_update23a(padapter, updated); - } - - return _SUCCESS; - } else -#endif - { - DBG_8723A_LEVEL(_drv_always_, "sta recv deauth reason code(%d) " - "sta:%pM\n", reason, mgmt->bssid); - - receive_disconnect23a(padapter, mgmt->bssid, reason); - } - pmlmepriv->LinkDetectInfo.bBusyTraffic = false; - - return _SUCCESS; -} - -static int -OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - unsigned short reason; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - - if (!ether_addr_equal(mgmt->bssid, - get_my_bssid23a(&pmlmeinfo->network))) - return _SUCCESS; - - reason = le16_to_cpu(mgmt->u.disassoc.reason_code); - - DBG_8723A("%s Reason code(%d)\n", __func__, reason); - -#ifdef CONFIG_8723AU_AP_MODE - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason code(%d)" - " sta:%pM\n", reason, mgmt->sa); - - psta = rtw_get_stainfo23a(pstapriv, mgmt->sa); - if (psta) { - u8 updated = 0; - - spin_lock_bh(&pstapriv->asoc_list_lock); - if (!list_empty(&psta->asoc_list)) { - list_del_init(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta23a(padapter, psta, - false, reason); - } - spin_unlock_bh(&pstapriv->asoc_list_lock); - - associated_clients_update23a(padapter, updated); - } - - return _SUCCESS; - } else -#endif - { - DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason " - "code(%d) sta:%pM\n", reason, mgmt->bssid); - - receive_disconnect23a(padapter, mgmt->bssid, reason); - } - pmlmepriv->LinkDetectInfo.bBusyTraffic = false; - return _SUCCESS; -} - -static int -OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - DBG_8723A("%s\n", __func__); - return _SUCCESS; -} - -static int -on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _FAIL; -} - -static int -OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int -OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int OnAction23a_back23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - u8 *addr; - struct sta_info *psta = NULL; - struct recv_reorder_ctrl *preorder_ctrl; - unsigned char category, action; - unsigned short tid, status, capab, params, reason_code = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* check RA matches or not */ - if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da)) - return _SUCCESS; - - DBG_8723A("%s\n", __func__); - - if ((pmlmeinfo->state&0x03) != MSR_AP) - if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) - return _SUCCESS; - - addr = mgmt->sa; - psta = rtw_get_stainfo23a(pstapriv, addr); - - if (!psta) - return _SUCCESS; - - category = mgmt->u.action.category; - if (category == WLAN_CATEGORY_BACK) { /* representing Block Ack */ - if (!pmlmeinfo->HT_enable) - return _SUCCESS; - /* action_code is located in the same place for all - action events, so pick any */ - action = mgmt->u.action.u.wme_action.action_code; - DBG_8723A("%s, action =%d\n", __func__, action); - switch (action) { - case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */ - memcpy(&pmlmeinfo->ADDBA_req, - &mgmt->u.action.u.addba_req.dialog_token, - sizeof(struct ADDBA_request)); - process_addba_req23a(padapter, - (u8 *)&pmlmeinfo->ADDBA_req, addr); - if (pmlmeinfo->bAcceptAddbaReq == true) - issue_action_BA23a(padapter, addr, - WLAN_ACTION_ADDBA_RESP, 0); - else { - /* reject ADDBA Req */ - issue_action_BA23a(padapter, addr, - WLAN_ACTION_ADDBA_RESP, 37); - } - break; - case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */ - status = get_unaligned_le16( - &mgmt->u.action.u.addba_resp.status); - capab = get_unaligned_le16( - &mgmt->u.action.u.addba_resp.capab); - tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; - if (status == 0) { /* successful */ - DBG_8723A("agg_enable for TID =%d\n", tid); - psta->htpriv.agg_enable_bitmap |= BIT(tid); - psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - } else - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - break; - - case WLAN_ACTION_DELBA: /* DELBA */ - params = get_unaligned_le16( - &mgmt->u.action.u.delba.params); - tid = params >> 12; - - if (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) { - preorder_ctrl = &psta->recvreorder_ctrl[tid]; - preorder_ctrl->enable = false; - preorder_ctrl->indicate_seq = 0xffff; - } else { - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - } - reason_code = get_unaligned_le16( - &mgmt->u.action.u.delba.reason_code); - /* todo: how to notify the host while receiving - DELETE BA */ - break; - default: - break; - } - } - return _SUCCESS; -} - -static int on_action_public23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u8 *pframe = skb->data; - int freq, channel; - - /* check RA matches or not */ - if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1)) - return _FAIL; - - channel = rtw_get_oper_ch23a(padapter); - - if (channel <= RTW_CH_MAX_2G_CHANNEL) - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_2GHZ); - else - freq = ieee80211_channel_to_frequency(channel, - NL80211_BAND_5GHZ); - - if (cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pframe, - skb->len, 0)) - return _SUCCESS; - - return _FAIL; -} - -static int -OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int -OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int -OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static int -OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) -{ - int i; - u8 category; - struct action_handler *ptable; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - - category = mgmt->u.action.category; - - for (i = 0; i < ARRAY_SIZE(OnAction23a_tbl); i++) { - ptable = &OnAction23a_tbl[i]; - - if (category == ptable->num) - ptable->func(padapter, precv_frame); - } - - return _SUCCESS; -} - -static int DoReserved23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -struct xmit_frame *alloc_mgtxmitframe23a(struct xmit_priv *pxmitpriv) -{ - struct xmit_frame *pmgntframe; - struct xmit_buf *pxmitbuf; - - pmgntframe = rtw_alloc_xmitframe23a_ext(pxmitpriv); - - if (!pmgntframe) { - DBG_8723A("%s(%s): alloc xmitframe fail\n", __func__, - pxmitpriv->adapter->pnetdev->name); - goto exit; - } - - pxmitbuf = rtw_alloc_xmitbuf23a_ext(pxmitpriv); - if (!pxmitbuf) { - DBG_8723A("%s(%s): alloc xmitbuf fail\n", __func__, - pxmitpriv->adapter->pnetdev->name); - rtw_free_xmitframe23a(pxmitpriv, pmgntframe); - pmgntframe = NULL; - goto exit; - } - - pmgntframe->frame_tag = MGNT_FRAMETAG; - pmgntframe->pxmitbuf = pxmitbuf; - pmgntframe->buf_addr = pxmitbuf->pbuf; - pxmitbuf->priv_data = pmgntframe; - -exit: - return pmgntframe; -} - -/**************************************************************************** - -Following are some TX functions for WiFi MLME - -*****************************************************************************/ - -void update_mgnt_tx_rate23a(struct rtw_adapter *padapter, u8 rate) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - pmlmeext->tx_rate = rate; - DBG_8723A("%s(): rate = %x\n", __func__, rate); -} - -void update_mgntframe_attrib23a(struct rtw_adapter *padapter, - struct pkt_attrib *pattrib) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - memset((u8 *)pattrib, 0, sizeof(struct pkt_attrib)); - - pattrib->hdrlen = 24; - pattrib->nr_frags = 1; - pattrib->priority = 7; - pattrib->mac_id = 0; - pattrib->qsel = 0x12; - - pattrib->pktlen = 0; - - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) - pattrib->raid = 6;/* b mode */ - else - pattrib->raid = 5;/* a/g mode */ - - pattrib->encrypt = 0; - pattrib->bswenc = false; - - pattrib->qos_en = false; - pattrib->ht_en = false; - pattrib->bwmode = HT_CHANNEL_WIDTH_20; - pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pattrib->sgi = false; - - pattrib->seqnum = pmlmeext->mgnt_seq; - - pattrib->retry_ctrl = true; -} - -void dump_mgntframe23a(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe) -{ - if (padapter->bSurpriseRemoved == true || - padapter->bDriverStopped == true) - return; - - rtl8723au_mgnt_xmit(padapter, pmgntframe); -} - -int dump_mgntframe23a_and_wait(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe, int timeout_ms) -{ - int ret = _FAIL; - unsigned long irqL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf; - struct submit_ctx sctx; - - if (padapter->bSurpriseRemoved == true || - padapter->bDriverStopped == true) - return ret; - - rtw_sctx_init23a(&sctx, timeout_ms); - pxmitbuf->sctx = &sctx; - - ret = rtl8723au_mgnt_xmit(padapter, pmgntframe); - - if (ret == _SUCCESS) - ret = rtw_sctx_wait23a(&sctx); - - spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL); - pxmitbuf->sctx = NULL; - spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL); - - return ret; -} - -int dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter, - struct xmit_frame *pmgntframe) -{ - int ret = _FAIL; - u32 timeout_ms = 500;/* 500ms */ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (padapter->bSurpriseRemoved == true || - padapter->bDriverStopped == true) - return _FAIL; - - mutex_lock(&pxmitpriv->ack_tx_mutex); - pxmitpriv->ack_tx = true; - - pmgntframe->ack_report = 1; - if (rtl8723au_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) - ret = rtw_ack_tx_wait23a(pxmitpriv, timeout_ms); - - pxmitpriv->ack_tx = false; - mutex_unlock(&pxmitpriv->ack_tx_mutex); - - return ret; -} - -static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode) -{ - u8 *ssid_ie; - int ssid_len_ori; - int len_diff = 0; - u8 *next_ie; - u32 remain_len; - - ssid_ie = rtw_get_ie23a(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len); - - /* DBG_8723A("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", - __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */ - - if (ssid_ie && ssid_len_ori > 0) { - switch (hidden_ssid_mode) { - case 1: - next_ie = ssid_ie + 2 + ssid_len_ori; - remain_len = ies_len -(next_ie-ies); - - ssid_ie[1] = 0; - memcpy(ssid_ie+2, next_ie, remain_len); - len_diff -= ssid_len_ori; - - break; - case 2: - memset(&ssid_ie[2], 0, ssid_len_ori); - break; - default: - break; - } - } - - return len_diff; -} - -void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_mgmt *mgmt; - unsigned int rate_len; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - const u8 *wps_ie; - u8 sr = 0; - int len_diff; - - /* DBG_8723A("%s\n", __func__); */ - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) { - DBG_8723A("%s, alloc mgnt frame fail\n", __func__); - return; - } -#ifdef CONFIG_8723AU_AP_MODE - spin_lock_bh(&pmlmepriv->bcn_update_lock); -#endif - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->qsel = 0x10; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); - mgmt->seq_ctrl = 0; - - ether_addr_copy(mgmt->da, bc_addr); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(cur_network)); - - /* timestamp will be inserted by hardware */ - - put_unaligned_le16(cur_network->beacon_interval, - &mgmt->u.beacon.beacon_int); - - put_unaligned_le16(cur_network->capability, - &mgmt->u.beacon.capab_info); - - pframe = mgmt->u.beacon.variable; - pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable); - - if ((pmlmeinfo->state & 0x03) == MSR_AP) { - u8 *iebuf; - int buflen; - /* DBG_8723A("ie len =%d\n", cur_network->IELength); */ - memcpy(pframe, cur_network->IEs, cur_network->IELength); - len_diff = update_hidden_ssid(pframe, cur_network->IELength, - pmlmeinfo->hidden_ssid_mode); - pframe += (cur_network->IELength+len_diff); - pattrib->pktlen += (cur_network->IELength+len_diff); - - iebuf = mgmt->u.beacon.variable; - buflen = pattrib->pktlen - - offsetof(struct ieee80211_mgmt, u.beacon.variable); - wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - iebuf, buflen); - - if (wps_ie && wps_ie[1] > 0) { - rtw_get_wps_attr_content23a(wps_ie, wps_ie[1], - WPS_ATTR_SELECTED_REGISTRAR, - (u8 *)&sr); - } - if (sr != 0) - set_fwstate(pmlmepriv, WIFI_UNDER_WPS); - else - _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS); - - goto _issue_bcn; - } - - /* SSID */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, - cur_network->Ssid.ssid_len, - cur_network->Ssid.ssid, &pattrib->pktlen); - - /* supported rates... */ - rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates); - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - ((rate_len > 8)? 8: rate_len), - cur_network->SupportedRates, &pattrib->pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *) - &cur_network->DSConfig, &pattrib->pktlen); - - /* if ((pmlmeinfo->state&0x03) == MSR_ADHOC) */ - { - u8 erpinfo = 0; - u32 ATIMWindow; - /* IBSS Parameter Set... */ - /* ATIMWindow = cur->ATIMWindow; */ - ATIMWindow = 0; - pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2, - (unsigned char *)&ATIMWindow, - &pattrib->pktlen); - - /* ERP IE */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1, - &erpinfo, &pattrib->pktlen); - } - - /* EXTERNDED SUPPORTED RATE */ - if (rate_len > 8) - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - rate_len - 8, - cur_network->SupportedRates + 8, - &pattrib->pktlen); - - /* todo:HT for adhoc */ - -_issue_bcn: - -#ifdef CONFIG_8723AU_AP_MODE - pmlmepriv->update_bcn = false; - - spin_unlock_bh(&pmlmepriv->bcn_update_lock); -#endif - - if ((pattrib->pktlen + TXDESC_SIZE) > 512) { - DBG_8723A("beacon frame too large\n"); - return; - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - /* DBG_8723A("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */ - if (timeout_ms > 0) - dump_mgntframe23a_and_wait(padapter, pmgntframe, timeout_ms); - else - dump_mgntframe23a(padapter, pmgntframe); -} - -static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_mgmt *mgmt; - unsigned char *mac, *bssid; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; -#ifdef CONFIG_8723AU_AP_MODE - const u8 *pwps_ie; - u8 *ssid_ie; - int ssid_ielen; - int ssid_ielen_diff; - u8 buf[MAX_IE_SZ]; -#endif - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - unsigned int rate_len; - - /* DBG_8723A("%s\n", __func__); */ - - if (cur_network->IELength > MAX_IE_SZ) - return; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) { - DBG_8723A("%s, alloc mgnt frame fail\n", __func__); - return; - } - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mac = myid(&padapter->eeprompriv); - bssid = cur_network->MacAddress; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); - - ether_addr_copy(mgmt->da, da); - ether_addr_copy(mgmt->sa, mac); - ether_addr_copy(mgmt->bssid, bssid); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - - /* timestamp will be inserted by hardware */ - put_unaligned_le16(cur_network->beacon_interval, - &mgmt->u.probe_resp.beacon_int); - - put_unaligned_le16(cur_network->capability, - &mgmt->u.probe_resp.capab_info); - - pframe = mgmt->u.probe_resp.variable; - pattrib->pktlen = - offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - - /* below for ad-hoc mode */ - -#ifdef CONFIG_8723AU_AP_MODE - if ((pmlmeinfo->state & 0x03) == MSR_AP) { - pwps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - cur_network->IEs, - cur_network->IELength); - - memcpy(pframe, cur_network->IEs, cur_network->IELength); - pframe += cur_network->IELength; - pattrib->pktlen += cur_network->IELength; - - /* retrieve SSID IE from cur_network->Ssid */ - - ssid_ie = rtw_get_ie23a(mgmt->u.probe_resp.variable, - WLAN_EID_SSID, &ssid_ielen, - pframe - mgmt->u.probe_resp.variable); - - ssid_ielen_diff = cur_network->Ssid.ssid_len - ssid_ielen; - - if (ssid_ie && cur_network->Ssid.ssid_len) { - uint remainder_ielen; - u8 *remainder_ie; - - remainder_ie = ssid_ie + 2; - - remainder_ielen = pframe - remainder_ie; - - DBG_8723A_LEVEL(_drv_warning_, "%s(%s): " - "remainder_ielen > MAX_IE_SZ\n", - __func__, padapter->pnetdev->name); - if (remainder_ielen > MAX_IE_SZ) - remainder_ielen = MAX_IE_SZ; - - memcpy(buf, remainder_ie, remainder_ielen); - memcpy(remainder_ie + ssid_ielen_diff, buf, - remainder_ielen); - *(ssid_ie + 1) = cur_network->Ssid.ssid_len; - memcpy(ssid_ie + 2, cur_network->Ssid.ssid, - cur_network->Ssid.ssid_len); - - pframe += ssid_ielen_diff; - pattrib->pktlen += ssid_ielen_diff; - } - } else -#endif - { - /* SSID */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, - cur_network->Ssid.ssid_len, - cur_network->Ssid.ssid, - &pattrib->pktlen); - - /* supported rates... */ - rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates); - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - ((rate_len > 8)? 8: rate_len), - cur_network->SupportedRates, - &pattrib->pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, - (unsigned char *)&cur_network->DSConfig, - &pattrib->pktlen); - - if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) { - u8 erpinfo = 0; - u32 ATIMWindow; - /* IBSS Parameter Set... */ - /* ATIMWindow = cur->ATIMWindow; */ - ATIMWindow = 0; - pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2, - (unsigned char *)&ATIMWindow, - &pattrib->pktlen); - - /* ERP IE */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1, - &erpinfo, &pattrib->pktlen); - } - - /* EXTERNDED SUPPORTED RATE */ - if (rate_len > 8) - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - rate_len - 8, - cur_network->SupportedRates + 8, - &pattrib->pktlen); - - /* todo:HT for adhoc */ - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe23a(padapter, pmgntframe); -} - -static int _issue_probereq(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, u8 *da, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - unsigned char *mac; - unsigned char bssrate[NumRates]; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - int bssrate_len = 0; - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - "+%s\n", __func__); - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - mac = myid(&padapter->eeprompriv); - - pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_PROBE_REQ); - - if (da) { - /* unicast probe request frame */ - ether_addr_copy(pwlanhdr->addr1, da); - ether_addr_copy(pwlanhdr->addr3, da); - } else { - /* broadcast probe request frame */ - ether_addr_copy(pwlanhdr->addr1, bc_addr); - ether_addr_copy(pwlanhdr->addr3, bc_addr); - } - - ether_addr_copy(pwlanhdr->addr2, mac); - - pwlanhdr->seq_ctrl = - cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - - pmlmeext->mgnt_seq++; - - pframe += sizeof (struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr); - - if (pssid) - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, pssid->ssid_len, - pssid->ssid, &pattrib->pktlen); - else - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, 0, NULL, - &pattrib->pktlen); - - get_rate_set23a(padapter, bssrate, &bssrate_len); - - if (bssrate_len > 8) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8, - bssrate, &pattrib->pktlen); - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - (bssrate_len - 8), (bssrate + 8), - &pattrib->pktlen); - } else { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - bssrate_len, bssrate, &pattrib->pktlen); - } - - /* add wps_ie for wps2.0 */ - if (pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie) { - memcpy(pframe, pmlmepriv->wps_probe_req_ie, - pmlmepriv->wps_probe_req_ie_len); - pframe += pmlmepriv->wps_probe_req_ie_len; - pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len; - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - "issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz); - - if (wait_ack) { - ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); - } else { - dump_mgntframe23a(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -static inline void issue_probereq(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, u8 *da) -{ - _issue_probereq(padapter, pssid, da, false); -} - -static int issue_probereq_ex(struct rtw_adapter *padapter, - struct cfg80211_ssid *pssid, u8 *da, - int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - unsigned long start = jiffies; - - do { - ret = _issue_probereq(padapter, pssid, da, - wait_ms > 0 ? true : false); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - - } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } - - if (try_cnt && wait_ms) { - if (da) - DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - da, rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } -exit: - return ret; -} - -/* if psta == NULL, indiate we are station(client) now... */ -static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta, - unsigned short status) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_mgmt *mgmt; - unsigned int val32; - u16 auth_algo; - int use_shared_key = 0; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.auth.variable); - - if (psta) { /* for AP mode */ -#ifdef CONFIG_8723AU_AP_MODE - unsigned short val16; - - ether_addr_copy(mgmt->da, psta->hwaddr); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, myid(&padapter->eeprompriv)); - - /* setting auth algo number */ - val16 = (u16)psta->authalg; - - if (status != WLAN_STATUS_SUCCESS) - val16 = 0; - - if (val16) - use_shared_key = 1; - - mgmt->u.auth.auth_alg = cpu_to_le16(val16); - - /* setting auth seq number */ - mgmt->u.auth.auth_transaction = - cpu_to_le16((u16)psta->auth_seq); - - /* setting status code... */ - mgmt->u.auth.status_code = cpu_to_le16(status); - - pframe = mgmt->u.auth.variable; - /* added challenging text... */ - if ((psta->auth_seq == 2) && - (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) - pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128, - psta->chg_txt, &pattrib->pktlen); -#endif - } else { - struct ieee80211_mgmt *iv_mgmt; - - ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network)); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, - get_my_bssid23a(&pmlmeinfo->network)); - - /* setting auth algo number */ - /* 0:OPEN System, 1:Shared key */ - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { - use_shared_key = 1; - auth_algo = WLAN_AUTH_SHARED_KEY; - } else - auth_algo = WLAN_AUTH_OPEN; - - /* DBG_8723A("%s auth_algo = %s auth_seq =%d\n", __func__, - (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED", - pmlmeinfo->auth_seq); */ - - /* setting IV for auth seq #3 */ - if ((pmlmeinfo->auth_seq == 3) && - (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && - (use_shared_key == 1)) { - u32 *piv = (u32 *)&mgmt->u.auth; - - iv_mgmt = (struct ieee80211_mgmt *)(pframe + 4); - /* DBG_8723A("==> iv(%d), key_index(%d)\n", - pmlmeinfo->iv, pmlmeinfo->key_index); */ - val32 = (pmlmeinfo->iv & 0x3fffffff) | - (pmlmeinfo->key_index << 30); - pmlmeinfo->iv++; - put_unaligned_le32(val32, piv); - - pattrib->pktlen += 4; - - pattrib->iv_len = IEEE80211_WEP_IV_LEN; - } else - iv_mgmt = mgmt; - - iv_mgmt->u.auth.auth_alg = cpu_to_le16(auth_algo); - - /* setting auth seq number */ - iv_mgmt->u.auth.auth_transaction = - cpu_to_le16(pmlmeinfo->auth_seq); - - /* setting status code... */ - iv_mgmt->u.auth.status_code = cpu_to_le16(status); - - pframe = iv_mgmt->u.auth.variable; - - /* then checking to see if sending challenging text... */ - if ((pmlmeinfo->auth_seq == 3) && - (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && - (use_shared_key == 1)) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128, - pmlmeinfo->chg_txt, - &pattrib->pktlen); - - mgmt->frame_control |= - cpu_to_le16(IEEE80211_FCTL_PROTECTED); - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - - pattrib->encrypt = WLAN_CIPHER_SUITE_WEP40; - - pattrib->icv_len = IEEE80211_WEP_ICV_LEN; - - pattrib->pktlen += pattrib->icv_len; - } - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - rtw_wep_encrypt23a(padapter, pmgntframe); - DBG_8723A("%s\n", __func__); - dump_mgntframe23a(padapter, pmgntframe); -} - -#ifdef CONFIG_8723AU_AP_MODE -static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status, - struct sta_info *pstat, u16 pkt_type) -{ - struct xmit_frame *pmgntframe; - struct ieee80211_mgmt *mgmt; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - const u8 *p; - u8 *ie = pnetwork->IEs; - - DBG_8723A("%s\n", __func__); - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | pkt_type); - - ether_addr_copy(mgmt->da, pstat->hwaddr); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network)); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - - pmlmeext->mgnt_seq++; - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = - offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); - - mgmt->u.assoc_resp.capab_info = cpu_to_le16(pnetwork->capability); - mgmt->u.assoc_resp.status_code = cpu_to_le16(status); - mgmt->u.assoc_resp.aid = cpu_to_le16(pstat->aid | BIT(14) | BIT(15)); - - pframe = mgmt->u.assoc_resp.variable; - - if (pstat->bssratelen <= 8) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - pstat->bssratelen, pstat->bssrateset, - &pattrib->pktlen); - } else { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8, - pstat->bssrateset, &pattrib->pktlen); - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - pstat->bssratelen - 8, - pstat->bssrateset + 8, &pattrib->pktlen); - } - - if (pstat->flags & WLAN_STA_HT && pmlmepriv->htpriv.ht_option) { - /* FILL HT CAP INFO IE */ - /* p = hostapd_eid_ht_capabilities_info(hapd, p); */ - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ie, - pnetwork->IELength); - if (p && p[1]) { - memcpy(pframe, p, p[1] + 2); - pframe += (p[1] + 2); - pattrib->pktlen += (p[1] + 2); - } - - /* FILL HT ADD INFO IE */ - /* p = hostapd_eid_ht_operation(hapd, p); */ - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie, - pnetwork->IELength); - if (p && p[1] > 0) { - memcpy(pframe, p, p[1] + 2); - pframe += (p[1] + 2); - pattrib->pktlen += (p[1] + 2); - } - } - - /* FILL WMM IE */ - if (pstat->flags & WLAN_STA_WME && pmlmepriv->qos_option) { - unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, - 0x01, 0x01}; - int ie_len = 0; - - for (p = ie; ; p += (ie_len + 2)) { - p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p, - pnetwork->IELength - (ie_len + 2)); - if (p) - ie_len = p[1]; - else - ie_len = 0; - if (p && !memcmp(p + 2, WMM_PARA_IE, 6)) { - memcpy(pframe, p, ie_len + 2); - pframe += (ie_len + 2); - pattrib->pktlen += (ie_len + 2); - - break; - } - - if (!p || ie_len == 0) - break; - } - } - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, - REALTEK_96B_IE, &pattrib->pktlen); - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe23a(padapter, pmgntframe); -} -#endif - -static void issue_assocreq(struct rtw_adapter *padapter) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - const u8 *p; - struct ieee80211_mgmt *mgmt; - unsigned int i, j, index = 0; - unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates]; - struct registry_priv *pregpriv = &padapter->registrypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - int bssrate_len = 0, sta_bssrate_len = 0, pie_len; - u8 *pie; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET; - mgmt = (struct ieee80211_mgmt *)pframe; - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ); - - ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network)); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network)); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - /* caps */ - put_unaligned_le16(pmlmeinfo->network.capability, - &mgmt->u.assoc_req.capab_info); - /* todo: listen interval for power saving */ - put_unaligned_le16(3, &mgmt->u.assoc_req.listen_interval); - - pframe = mgmt->u.assoc_req.variable; - pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.assoc_req.variable); - - /* SSID */ - pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, - pmlmeinfo->network.Ssid.ssid_len, - pmlmeinfo->network.Ssid.ssid, &pattrib->pktlen); - - /* supported rate & extended supported rate */ - - get_rate_set23a(padapter, sta_bssrate, &sta_bssrate_len); - /* DBG_8723A("sta_bssrate_len =%d\n", sta_bssrate_len); */ - - /* for JAPAN, channel 14 can only uses B Mode(CCK) */ - if (pmlmeext->cur_channel == 14) - sta_bssrate_len = 4; - - /* for (i = 0; i < sta_bssrate_len; i++) { */ - /* DBG_8723A("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */ - /* */ - - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - if (pmlmeinfo->network.SupportedRates[i] == 0) - break; - DBG_8723A("network.SupportedRates[%d]=%02X\n", i, - pmlmeinfo->network.SupportedRates[i]); - } - - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - if (pmlmeinfo->network.SupportedRates[i] == 0) - break; - - /* Check if the AP's supported rates are also - supported by STA. */ - for (j = 0; j < sta_bssrate_len; j++) { - /* Avoid the proprietary data rate (22Mbps) of - Handlink WSG-4000 AP */ - if ((pmlmeinfo->network.SupportedRates[i] | - IEEE80211_BASIC_RATE_MASK) == - (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) { - /* DBG_8723A("match i = %d, j =%d\n", i, j); */ - break; - } - } - - if (j == sta_bssrate_len) { - /* the rate is not supported by STA */ - DBG_8723A("%s(): the rate[%d]=%02X is not supported by " - "STA!\n", __func__, i, - pmlmeinfo->network.SupportedRates[i]); - } else { - /* the rate is supported by STA */ - bssrate[index++] = pmlmeinfo->network.SupportedRates[i]; - } - } - - bssrate_len = index; - DBG_8723A("bssrate_len = %d\n", bssrate_len); - - if (bssrate_len == 0) { - rtw_free_xmitbuf23a(pxmitpriv, pmgntframe->pxmitbuf); - rtw_free_xmitframe23a(pxmitpriv, pmgntframe); - goto exit; /* don't connect to AP if no joint supported rate */ - } - - if (bssrate_len > 8) { - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8, - bssrate, &pattrib->pktlen); - pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES, - (bssrate_len - 8), (bssrate + 8), - &pattrib->pktlen); - } else - pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, - bssrate_len, bssrate, &pattrib->pktlen); - - /* RSN */ - - pie = pmlmeinfo->network.IEs; - pie_len = pmlmeinfo->network.IELength; - - p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len); - if (p) - pframe = rtw_set_ie23a(pframe, WLAN_EID_RSN, p[1], p + 2, - &pattrib->pktlen); - - /* HT caps */ - if (padapter->mlmepriv.htpriv.ht_option) { - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len); - - if (p && !is_ap_in_tkip23a(padapter)) { - struct ieee80211_ht_cap *cap = &pmlmeinfo->ht_cap; - - memcpy(cap, p + 2, sizeof(struct ieee80211_ht_cap)); - - /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */ - if (pregpriv->cbw40_enable == 0) { - cap->cap_info &= ~cpu_to_le16( - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_SUP_WIDTH_20_40); - } else { - cap->cap_info |= cpu_to_le16( - IEEE80211_HT_CAP_SUP_WIDTH_20_40); - } - - /* todo: disable SM power save mode */ - cap->cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SM_PS); - - rf_type = rtl8723a_get_rf_type(padapter); - /* switch (pregpriv->rf_config) */ - switch (rf_type) { - case RF_1T1R: - /* RX STBC One spatial stream */ - if (pregpriv->rx_stbc) - cap->cap_info |= cpu_to_le16(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); - - memcpy(&cap->mcs, MCS_rate_1R23A, 16); - break; - - case RF_2T2R: - case RF_1T2R: - default: - /* enable for 2.4/5 GHz */ - if (pregpriv->rx_stbc == 0x3 || - (pmlmeext->cur_wireless_mode & - WIRELESS_11_24N && - /* enable for 2.4GHz */ - pregpriv->rx_stbc == 0x1) || - (pmlmeext->cur_wireless_mode & - WIRELESS_11_5N && - pregpriv->rx_stbc == 0x2) || - /* enable for 5GHz */ - pregpriv->wifi_spec == 1) { - DBG_8723A("declare supporting RX " - "STBC\n"); - /* RX STBC two spatial stream */ - cap->cap_info |= cpu_to_le16(2 << IEEE80211_HT_CAP_RX_STBC_SHIFT); - } - memcpy(&cap->mcs, MCS_rate_2R23A, 16); - break; - } - - if (rtl8723a_BT_coexist(padapter) && - rtl8723a_BT_using_antenna_1(padapter)) { - /* set to 8K */ - cap->ampdu_params_info &= - ~IEEE80211_HT_AMPDU_PARM_FACTOR; -/* cap->ampdu_params_info |= MAX_AMPDU_FACTOR_8K */ - } - - pframe = rtw_set_ie23a(pframe, WLAN_EID_HT_CAPABILITY, - p[1], (u8 *)&pmlmeinfo->ht_cap, - &pattrib->pktlen); - } - } - - /* vendor specific IE, such as WPA, WMM, WPS */ - for (i = 0; i < pmlmeinfo->network.IELength;) { - p = pmlmeinfo->network.IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) || - !memcmp(p + 2, WMM_OUI23A, 4) || - !memcmp(p + 2, WPS_OUI23A, 4)) { - u8 plen = p[1]; - - if (!padapter->registrypriv.wifi_spec) { - /* Commented by Kurt 20110629 */ - /* In some older APs, WPS handshake */ - /* would be fail if we append vender - extensions informations to AP */ - if (!memcmp(p + 2, WPS_OUI23A, 4)) - plen = 14; - } - pframe = rtw_set_ie23a(pframe, - WLAN_EID_VENDOR_SPECIFIC, - plen, p + 2, - &pattrib->pktlen); - } - break; - - default: - break; - } - - i += p[1] + 2; - } - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) - pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, - REALTEK_96B_IE, &pattrib->pktlen); - - pattrib->last_txcmdsz = pattrib->pktlen; - dump_mgntframe23a(padapter, pmgntframe); - - ret = _SUCCESS; - -exit: - pmlmepriv->assoc_req_len = 0; - if (ret == _SUCCESS) { - kfree(pmlmepriv->assoc_req); - pmlmepriv->assoc_req = kmalloc(pattrib->pktlen, GFP_ATOMIC); - if (pmlmepriv->assoc_req) { - memcpy(pmlmepriv->assoc_req, mgmt, pattrib->pktlen); - pmlmepriv->assoc_req_len = pattrib->pktlen; - } - } else - kfree(pmlmepriv->assoc_req); -} - -/* when wait_ack is true, this function should be called at process context */ -static int _issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da, - unsigned int power_mode, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_hdr *pwlanhdr; - struct xmit_priv *pxmitpriv; - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - - /* DBG_8723A("%s:%d\n", __func__, power_mode); */ - - if (!padapter) - goto exit; - - pxmitpriv = &padapter->xmitpriv; - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->retry_ctrl = false; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_hdr *)pframe; - - pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC); - - if ((pmlmeinfo->state&0x03) == MSR_AP) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS); - else if ((pmlmeinfo->state&0x03) == MSR_INFRA) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS); - - if (power_mode) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - - ether_addr_copy(pwlanhdr->addr1, da); - ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv)); - ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network)); - - pwlanhdr->seq_ctrl = - cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pframe += sizeof(struct ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) - ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); - else { - dump_mgntframe23a(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -/* when wait_ms >0 , this function should be called at process context */ -/* da == NULL for station mode */ -int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da, - unsigned int power_mode, int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - unsigned long start = jiffies; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* da == NULL, assume it's null data for sta to ap*/ - if (da == NULL) - da = get_my_bssid23a(&pmlmeinfo->network); - - do { - ret = _issue_nulldata23a(padapter, da, power_mode, - wait_ms > 0 ? true : false); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - - } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } - - if (try_cnt && wait_ms) { - if (da) - DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - da, rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } -exit: - return ret; -} - -/* when wait_ack is true, this function should be called at process context */ -static int _issue_qos_nulldata23a(struct rtw_adapter *padapter, - unsigned char *da, u16 tid, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_qos_hdr *pwlanhdr; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - DBG_8723A("%s\n", __func__); - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - pattrib->hdrlen += 2; - pattrib->qos_en = true; - pattrib->eosp = 1; - pattrib->ack_policy = 0; - pattrib->mdata = 0; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct ieee80211_qos_hdr *)pframe; - - pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_QOS_NULLFUNC); - - if ((pmlmeinfo->state&0x03) == MSR_AP) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS); - else if ((pmlmeinfo->state&0x03) == MSR_INFRA) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS); - - if (pattrib->mdata) - pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); - - pwlanhdr->qos_ctrl = cpu_to_le16(tid & IEEE80211_QOS_CTL_TID_MASK); - pwlanhdr->qos_ctrl |= cpu_to_le16((pattrib->ack_policy << 5) & - IEEE80211_QOS_CTL_ACK_POLICY_MASK); - if (pattrib->eosp) - pwlanhdr->qos_ctrl |= cpu_to_le16(IEEE80211_QOS_CTL_EOSP); - - ether_addr_copy(pwlanhdr->addr1, da); - ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv)); - ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network)); - - pwlanhdr->seq_ctrl = - cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pframe += sizeof(struct ieee80211_qos_hdr); - pattrib->pktlen = sizeof(struct ieee80211_qos_hdr); - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) - ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); - else { - dump_mgntframe23a(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -/* when wait_ms >0 , this function should be called at process context */ -/* da == NULL for station mode */ -int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da, - u16 tid, int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - unsigned long start = jiffies; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* da == NULL, assume it's null data for sta to ap*/ - if (da == NULL) - da = get_my_bssid23a(&pmlmeinfo->network); - - do { - ret = _issue_qos_nulldata23a(padapter, da, tid, - wait_ms > 0 ? true : false); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } - - if (try_cnt && wait_ms) { - if (da) - DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - da, rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } -exit: - return ret; -} - -static int _issue_deauth(struct rtw_adapter *padapter, unsigned char *da, - unsigned short reason, u8 wait_ack) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct ieee80211_mgmt *mgmt; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - int ret = _FAIL; - - /* DBG_8723A("%s to %pM\n", __func__, da); */ - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - pattrib->retry_ctrl = false; - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET); - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); - - ether_addr_copy(mgmt->da, da); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network)); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 2; - - mgmt->u.deauth.reason_code = cpu_to_le16(reason); - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) - ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe); - else { - dump_mgntframe23a(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da, - unsigned short reason) -{ - DBG_8723A("%s to %pM\n", __func__, da); - return _issue_deauth(padapter, da, reason, false); -} - -static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da, - unsigned short reason, int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - unsigned long start = jiffies; - - do { - ret = _issue_deauth(padapter, da, reason, - wait_ms >0 ? true : false); - - i++; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - msleep(wait_ms); - - } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; - goto exit; - } - - if (try_cnt && wait_ms) { - if (da) - DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - da, rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - else - DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n", - __func__, padapter->pnetdev->name, - rtw_get_oper_ch23a(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, - jiffies_to_msecs(jiffies - start)); - } -exit: - return ret; -} - -void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter, - u8 *ra, u8 new_ch, u8 ch_offset) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct ieee80211_mgmt *mgmt; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - DBG_8723A("%s(%s): ra=%pM, ch:%u, offset:%u\n", - __func__, padapter->pnetdev->name, ra, new_ch, ch_offset); - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET); - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); - - ether_addr_copy(mgmt->da, ra); /* RA */ - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); /* TA */ - ether_addr_copy(mgmt->bssid, ra); /* DA = RA */ - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; - mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH; - - pframe = mgmt->u.action.u.chan_switch.variable; - pattrib->pktlen = offsetof(struct ieee80211_mgmt, - u.action.u.chan_switch.variable); - - pframe = rtw_set_ie23a_ch_switch (pframe, &pattrib->pktlen, 0, - new_ch, 0); - pframe = rtw_set_ie23a_secondary_ch_offset(pframe, &pattrib->pktlen, - hal_ch_offset_to_secondary_ch_offset23a(ch_offset)); - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe23a(padapter, pmgntframe); -} - -void issue_action_BA23a(struct rtw_adapter *padapter, - const unsigned char *raddr, - unsigned char action, unsigned short status) -{ - u16 start_seq; - u16 BA_para_set; - u16 BA_starting_seqctrl; - u16 BA_para; - int max_rx_ampdu_factor; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct ieee80211_mgmt *mgmt; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - struct registry_priv *pregpriv = &padapter->registrypriv; - u8 tendaAPMac[] = {0xC8, 0x3A, 0x35}; - - DBG_8723A("%s, action =%d, status =%d\n", __func__, action, status); - - pmgntframe = alloc_mgtxmitframe23a(pxmitpriv); - if (!pmgntframe) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib23a(padapter, pattrib); - - memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET); - - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); - - ether_addr_copy(mgmt->da, raddr); - ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); - ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network)); - - mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq)); - pmlmeext->mgnt_seq++; - - mgmt->u.action.category = WLAN_CATEGORY_BACK; - - pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 1; - - switch (action) { - case WLAN_ACTION_ADDBA_REQ: - pattrib->pktlen += sizeof(mgmt->u.action.u.addba_req); - - mgmt->u.action.u.addba_req.action_code = action; - - do { - pmlmeinfo->dialogToken++; - } while (pmlmeinfo->dialogToken == 0); - - mgmt->u.action.u.addba_req.dialog_token = - pmlmeinfo->dialogToken; - - if (rtl8723a_BT_coexist(padapter) && - rtl8723a_BT_using_antenna_1(padapter) && - (pmlmeinfo->assoc_AP_vendor != broadcomAP || - memcmp(raddr, tendaAPMac, 3))) { - /* A-MSDU NOT Supported */ - BA_para_set = 0; - /* immediate Block Ack */ - BA_para_set |= (1 << 1) & - IEEE80211_ADDBA_PARAM_POLICY_MASK; - /* TID */ - BA_para_set |= (status << 2) & - IEEE80211_ADDBA_PARAM_TID_MASK; - /* max buffer size is 8 MSDU */ - BA_para_set |= (8 << 6) & - IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; - } else { - /* immediate ack & 64 buffer size */ - BA_para_set = 0x1002 | ((status & 0xf) << 2); - } - - put_unaligned_le16(BA_para_set, - &mgmt->u.action.u.addba_req.capab); - - /* 5ms */ - put_unaligned_le16(5000, &mgmt->u.action.u.addba_req.timeout); - - psta = rtw_get_stainfo23a(pstapriv, raddr); - if (psta) { - int idx; - - idx = status & 0x07; - start_seq = - (psta->sta_xmitpriv.txseq_tid[idx] & 0xfff) + 1; - - DBG_8723A("BA_starting_seqctrl = %d for TID =%d\n", - start_seq, idx); - - psta->BA_starting_seqctrl[idx] = start_seq; - - BA_starting_seqctrl = start_seq << 4; - } else - BA_starting_seqctrl = 0; - - put_unaligned_le16(BA_starting_seqctrl, - &mgmt->u.action.u.addba_req.start_seq_num); - - break; - - case WLAN_ACTION_ADDBA_RESP: - pattrib->pktlen += sizeof(mgmt->u.action.u.addba_resp); - - mgmt->u.action.u.addba_resp.action_code = action; - mgmt->u.action.u.addba_resp.dialog_token = - pmlmeinfo->ADDBA_req.dialog_token; - put_unaligned_le16(status, - &mgmt->u.action.u.addba_resp.status); - - GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, - &max_rx_ampdu_factor); - - BA_para = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f; - if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K) - BA_para_set = BA_para | 0x1000; /* 64 buffer size */ - else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K) - BA_para_set = BA_para | 0x0800; /* 32 buffer size */ - else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K) - BA_para_set = BA_para | 0x0400; /* 16 buffer size */ - else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K) - BA_para_set = BA_para | 0x0200; /* 8 buffer size */ - else - BA_para_set = BA_para | 0x1000; /* 64 buffer size */ - - if (rtl8723a_BT_coexist(padapter) && - rtl8723a_BT_using_antenna_1(padapter) && - (pmlmeinfo->assoc_AP_vendor != broadcomAP || - memcmp(raddr, tendaAPMac, 3))) { - /* max buffer size is 8 MSDU */ - BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; - BA_para_set |= (8 << 6) & - IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; - } - - if (pregpriv->ampdu_amsdu == 0)/* disabled */ - BA_para_set &= ~BIT(0); - else if (pregpriv->ampdu_amsdu == 1)/* enabled */ - BA_para_set |= BIT(0); - - put_unaligned_le16(BA_para_set, - &mgmt->u.action.u.addba_resp.capab); - - mgmt->u.action.u.addba_resp.timeout - = pmlmeinfo->ADDBA_req.BA_timeout_value; - - pattrib->pktlen += 8; - break; - case WLAN_ACTION_DELBA: - pattrib->pktlen += sizeof(mgmt->u.action.u.delba); - - mgmt->u.action.u.delba.action_code = action; - BA_para_set = (status & 0x1F) << 3; - mgmt->u.action.u.delba.params = cpu_to_le16(BA_para_set); - mgmt->u.action.u.delba.reason_code = - cpu_to_le16(WLAN_REASON_QSTA_NOT_USE); - - pattrib->pktlen += 5; - break; - default: - break; - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe23a(padapter, pmgntframe); -} - -int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta = NULL; - /* struct recv_reorder_ctrl *preorder_ctrl; */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u16 tid; - - if ((pmlmeinfo->state&0x03) != MSR_AP) - if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) - return _SUCCESS; - - psta = rtw_get_stainfo23a(pstapriv, addr); - if (psta == NULL) - return _SUCCESS; - - if (initiator == 0) { /* recipient */ - for (tid = 0; tid < MAXTID; tid++) { - if (psta->recvreorder_ctrl[tid].enable == true) { - DBG_8723A("rx agg disable tid(%d)\n", tid); - issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F)); - psta->recvreorder_ctrl[tid].enable = false; - psta->recvreorder_ctrl[tid].indicate_seq = 0xffff; - } - } - } else if (initiator == 1) { /* originator */ - for (tid = 0; tid < MAXTID; tid++) { - if (psta->htpriv.agg_enable_bitmap & BIT(tid)) { - DBG_8723A("tx agg disable tid(%d)\n", tid); - issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F)); - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - - } - } - } - return _SUCCESS; -} - -int send_beacon23a(struct rtw_adapter *padapter) -{ - bool bxmitok; - int issue = 0; - int poll = 0; - unsigned long start = jiffies; - unsigned int passing_time; - - rtl8723a_bcn_valid(padapter); - do { - issue_beacon23a(padapter, 100); - issue++; - do { - yield(); - bxmitok = rtl8723a_get_bcn_valid(padapter); - poll++; - } while ((poll % 10) != 0 && !bxmitok && - !padapter->bSurpriseRemoved && - !padapter->bDriverStopped); - - } while (!bxmitok && issue<100 && !padapter->bSurpriseRemoved && - !padapter->bDriverStopped); - - if (padapter->bSurpriseRemoved || padapter->bDriverStopped) - return _FAIL; - - passing_time = jiffies_to_msecs(jiffies - start); - - if (!bxmitok) { - DBG_8723A("%s fail! %u ms\n", __func__, passing_time); - return _FAIL; - } else { - - if (passing_time > 100 || issue > 3) - DBG_8723A("%s success, issue:%d, poll:%d, %u ms\n", - __func__, issue, poll, passing_time); - return _SUCCESS; - } -} - -/**************************************************************************** - -Following are some utitity functions for WiFi MLME - -*****************************************************************************/ - -bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel) -{ - - int i = 0; - u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, - 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, - 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, - 134, 136, 138, 140, 149, 151, 153, 155, 157, 159, - 161, 163, 165}; - for (i = 0; i < sizeof(Channel_5G); i++) - if (channel == Channel_5G[i]) - return true; - return false; -} - -static void rtw_site_survey(struct rtw_adapter *padapter) -{ - unsigned char survey_channel = 0; - enum rt_scan_type ScanType = SCAN_PASSIVE; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct rtw_ieee80211_channel *ch; - - if (pmlmeext->sitesurvey_res.channel_idx < - pmlmeext->sitesurvey_res.ch_num) { - ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx]; - survey_channel = ch->hw_value; - ScanType = (ch->flags & IEEE80211_CHAN_NO_IR) ? - SCAN_PASSIVE : SCAN_ACTIVE; - } - - if (survey_channel != 0) { - /* PAUSE 4-AC Queue when site_survey */ - if (pmlmeext->sitesurvey_res.channel_idx == 0) - set_channel_bwmode23a(padapter, survey_channel, - HAL_PRIME_CHNL_OFFSET_DONT_CARE, - HT_CHANNEL_WIDTH_20); - else - SelectChannel23a(padapter, survey_channel); - - if (ScanType == SCAN_ACTIVE) /* obey the channel plan setting... */ - { - int i; - - for (i = 0;i<RTW_SSID_SCAN_AMOUNT;i++) { - if (pmlmeext->sitesurvey_res.ssid[i].ssid_len) { - /* todo: to issue two probe req??? */ - issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL); - /* msleep(SURVEY_TO>>1); */ - issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL); - } - } - - if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) { - /* todo: to issue two probe req??? */ - issue_probereq(padapter, NULL, NULL); - /* msleep(SURVEY_TO>>1); */ - issue_probereq(padapter, NULL, NULL); - } - } - - set_survey_timer(pmlmeext, pmlmeext->chan_scan_time); - } else { - /* channel number is 0 or this channel is not valid. */ - pmlmeext->sitesurvey_res.state = SCAN_COMPLETE; - - /* switch back to the original channel */ - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, - pmlmeext->cur_bwmode); - - /* flush 4-AC Queue after rtw_site_survey */ - /* val8 = 0; */ - - /* config MSR */ - rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3); - - /* restore RX GAIN */ - rtl8723a_set_initial_gain(padapter, 0xff); - /* turn on dynamic functions */ - rtl8723a_odm_support_ability_restore(padapter); - - if (is_client_associated_to_ap23a(padapter) == true) - issue_nulldata23a(padapter, NULL, 0, 3, 500); - - rtl8723a_mlme_sitesurvey(padapter, 0); - - report_surveydone_event23a(padapter); - - pmlmeext->chan_scan_time = SURVEY_TO; - pmlmeext->sitesurvey_res.state = SCAN_DISABLE; - } -} - -/* collect bss info from Beacon and Probe request/response frames. */ -static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *bssid; - const u8 *p; - u8 *pie; - unsigned int length; - int i; - - length = skb->len; - - bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC); - if (!bssid) - return NULL; - - if (ieee80211_is_beacon(mgmt->frame_control)) { - length -= offsetof(struct ieee80211_mgmt, u.beacon.variable); - pie = mgmt->u.beacon.variable; - bssid->reserved = 1; - bssid->capability = - get_unaligned_le16(&mgmt->u.beacon.capab_info); - bssid->beacon_interval = - get_unaligned_le16(&mgmt->u.beacon.beacon_int); - bssid->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp); - } else if (ieee80211_is_probe_req(mgmt->frame_control)) { - length -= offsetof(struct ieee80211_mgmt, u.probe_req.variable); - pie = mgmt->u.probe_req.variable; - bssid->reserved = 2; - bssid->capability = 0; - bssid->beacon_interval = - padapter->registrypriv.dev_network.beacon_interval; - bssid->tsf = 0; - } else if (ieee80211_is_probe_resp(mgmt->frame_control)) { - length -= - offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - pie = mgmt->u.probe_resp.variable; - bssid->reserved = 3; - bssid->capability = - get_unaligned_le16(&mgmt->u.probe_resp.capab_info); - bssid->beacon_interval = - get_unaligned_le16(&mgmt->u.probe_resp.beacon_int); - bssid->tsf = get_unaligned_le64(&mgmt->u.probe_resp.timestamp); - } else { - length -= offsetof(struct ieee80211_mgmt, u.beacon.variable); - pie = mgmt->u.beacon.variable; - bssid->reserved = 0; - bssid->capability = - get_unaligned_le16(&mgmt->u.beacon.capab_info); - bssid->beacon_interval = - padapter->registrypriv.dev_network.beacon_interval; - bssid->tsf = 0; - } - - if (length > MAX_IE_SZ) { - /* DBG_8723A("IE too long for survey event\n"); */ - kfree(bssid); - return NULL; - } - - bssid->Length = offsetof(struct wlan_bssid_ex, IEs) + length; - - /* below is to copy the information element */ - bssid->IELength = length; - memcpy(bssid->IEs, pie, bssid->IELength); - - /* get the signal strength */ - /* in dBM.raw data */ - bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower; - bssid->SignalQuality = - precv_frame->attrib.phy_info.SignalQuality;/* in percentage */ - bssid->SignalStrength = - precv_frame->attrib.phy_info.SignalStrength;/* in percentage */ - - /* checking SSID */ - p = cfg80211_find_ie(WLAN_EID_SSID, bssid->IEs, bssid->IELength); - - if (!p) { - DBG_8723A("marc: cannot find SSID for survey event\n"); - goto fail; - } - - if (p[1] > IEEE80211_MAX_SSID_LEN) { - DBG_8723A("%s()-%d: IE too long (%d) for survey " - "event\n", __func__, __LINE__, p[1]); - goto fail; - } - memcpy(bssid->Ssid.ssid, p + 2, p[1]); - bssid->Ssid.ssid_len = p[1]; - - /* checking rate info... */ - i = 0; - p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, bssid->IEs, bssid->IELength); - if (p) { - if (p[1] > NDIS_802_11_LENGTH_RATES_EX) { - DBG_8723A("%s()-%d: IE too long (%d) for survey " - "event\n", __func__, __LINE__, p[1]); - goto fail; - } - memcpy(bssid->SupportedRates, p + 2, p[1]); - i = p[1]; - } - - p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, bssid->IEs, - bssid->IELength); - if (p) { - if (p[1] > (NDIS_802_11_LENGTH_RATES_EX-i)) { - DBG_8723A("%s()-%d: IE too long (%d) for survey " - "event\n", __func__, __LINE__, p[1]); - goto fail; - } - memcpy(bssid->SupportedRates + i, p + 2, p[1]); - } - - /* Checking for DSConfig */ - p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bssid->IEs, bssid->IELength); - - bssid->DSConfig = 0; - - if (p) { - bssid->DSConfig = p[2]; - } else {/* In 5G, some ap do not have DSSET IE */ - /* checking HT info for channel */ - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, bssid->IEs, - bssid->IELength); - if (p) { - struct ieee80211_ht_operation *HT_info = - (struct ieee80211_ht_operation *)(p + 2); - bssid->DSConfig = HT_info->primary_chan; - } else /* use current channel */ - bssid->DSConfig = rtw_get_oper_ch23a(padapter); - } - - if (ieee80211_is_probe_req(mgmt->frame_control)) { - /* FIXME */ - bssid->ifmode = NL80211_IFTYPE_STATION; - ether_addr_copy(bssid->MacAddress, mgmt->sa); - bssid->Privacy = 1; - return bssid; - } - - if (bssid->capability & WLAN_CAPABILITY_ESS) { - bssid->ifmode = NL80211_IFTYPE_STATION; - ether_addr_copy(bssid->MacAddress, mgmt->sa); - } else { - bssid->ifmode = NL80211_IFTYPE_ADHOC; - ether_addr_copy(bssid->MacAddress, mgmt->bssid); - } - - if (bssid->capability & WLAN_CAPABILITY_PRIVACY) - bssid->Privacy = 1; - else - bssid->Privacy = 0; - - bssid->ATIMWindow = 0; - - /* 20/40 BSS Coexistence check */ - if (pregistrypriv->wifi_spec == 1 && - pmlmeinfo->bwmode_updated == false) { - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, bssid->IEs, - bssid->IELength); - if (p && p[1] > 0) { - struct ieee80211_ht_cap *pHT_caps; - - pHT_caps = (struct ieee80211_ht_cap *)(p + 2); - - if (pHT_caps->cap_info & - cpu_to_le16(IEEE80211_HT_CAP_40MHZ_INTOLERANT)) - pmlmepriv->num_FortyMHzIntolerant++; - } else - pmlmepriv->num_sta_no_ht++; - } - - - /* mark bss info receiving from nearby channel as SignalQuality 101 */ - if (bssid->DSConfig != rtw_get_oper_ch23a(padapter)) - bssid->SignalQuality = 101; - - return bssid; -fail: - kfree (bssid); - return NULL; -} - -static void start_create_ibss(struct rtw_adapter *padapter) -{ - unsigned short caps; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - - pmlmeext->cur_channel = (u8)pnetwork->DSConfig; - pmlmeinfo->bcn_interval = pnetwork->beacon_interval; - - /* update wireless mode */ - update_wireless_mode23a(padapter); - - /* update capability */ - caps = pnetwork->capability; - update_capinfo23a(padapter, caps); - if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc master */ - rtl8723a_set_sec_cfg(padapter, 0xcf); - - /* switch channel */ - /* SelectChannel23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */ - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - - rtl8723a_SetBeaconRelatedRegisters(padapter); - - /* set msr to MSR_ADHOC */ - pmlmeinfo->state = MSR_ADHOC; - rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3); - - /* issue beacon */ - if (send_beacon23a(padapter) == _FAIL) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "issuing beacon frame fail....\n"); - - report_join_res23a(padapter, -1); - pmlmeinfo->state = MSR_NOLINK; - } else { - hw_var_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress); - hw_var_set_mlme_join(padapter, 0); - - report_join_res23a(padapter, 1); - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - } - } else { - DBG_8723A("%s: invalid cap:%x\n", __func__, caps); - return; - } -} - -static void start_clnt_join(struct rtw_adapter *padapter) -{ - unsigned short caps; - u8 val8; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - int beacon_timeout; - - pmlmeext->cur_channel = (u8)pnetwork->DSConfig; - pmlmeinfo->bcn_interval = pnetwork->beacon_interval; - - /* update wireless mode */ - update_wireless_mode23a(padapter); - - /* update capability */ - caps = pnetwork->capability; - update_capinfo23a(padapter, caps); - if (caps & WLAN_CAPABILITY_ESS) { - /* switch channel */ - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - rtl8723a_set_media_status(padapter, MSR_INFRA); - - val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? - 0xcc: 0xcf; - - rtl8723a_set_sec_cfg(padapter, val8); - - /* switch channel */ - /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */ - - /* here wait for receiving the beacon to start auth */ - /* and enable a timer */ - beacon_timeout = decide_wait_for_beacon_timeout23a(pmlmeinfo->bcn_interval); - set_link_timer(pmlmeext, beacon_timeout); - mod_timer(&padapter->mlmepriv.assoc_timer, jiffies + - msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout)); - pmlmeinfo->state = WIFI_FW_AUTH_NULL | MSR_INFRA; - } else if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc client */ - rtl8723a_set_media_status(padapter, MSR_ADHOC); - - rtl8723a_set_sec_cfg(padapter, 0xcf); - - /* switch channel */ - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - rtl8723a_SetBeaconRelatedRegisters(padapter); - - pmlmeinfo->state = MSR_ADHOC; - - report_join_res23a(padapter, 1); - } else { - /* DBG_8723A("marc: invalid cap:%x\n", caps); */ - return; - } -} - -static void start_clnt_auth(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - del_timer_sync(&pmlmeext->link_timer); - - pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL); - pmlmeinfo->state |= WIFI_FW_AUTH_STATE; - - pmlmeinfo->auth_seq = 1; - pmlmeinfo->reauth_count = 0; - pmlmeinfo->reassoc_count = 0; - pmlmeinfo->link_count = 0; - pmlmeext->retry = 0; - - /* Because of AP's not receiving deauth before */ - /* AP may: 1)not response auth or 2)deauth us after link is complete */ - /* issue deauth before issuing auth to deal with the situation */ - /* Commented by Albert 2012/07/21 */ - /* For the Win8 P2P connection, it will be hard to have a - successful connection if this Wi-Fi doesn't connect to it. */ - issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress, - WLAN_REASON_DEAUTH_LEAVING); - - DBG_8723A_LEVEL(_drv_always_, "start auth\n"); - issue_auth(padapter, NULL, 0); - - set_link_timer(pmlmeext, REAUTH_TO); -} - -static void start_clnt_assoc(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - del_timer_sync(&pmlmeext->link_timer); - - pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE)); - pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE); - - issue_assocreq(padapter); - - set_link_timer(pmlmeext, REASSOC_TO); -} - -int receive_disconnect23a(struct rtw_adapter *padapter, - unsigned char *MacAddr, unsigned short reason) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* check A3 */ - if (!ether_addr_equal(MacAddr, get_my_bssid23a(&pmlmeinfo->network))) - return _SUCCESS; - - DBG_8723A("%s\n", __func__); - - if ((pmlmeinfo->state&0x03) == MSR_INFRA) { - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { - pmlmeinfo->state = MSR_NOLINK; - report_del_sta_event23a(padapter, MacAddr, reason); - - } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) { - pmlmeinfo->state = MSR_NOLINK; - report_join_res23a(padapter, -2); - } - } - - return _SUCCESS; -} - -static void process_80211d(struct rtw_adapter *padapter, - struct wlan_bssid_ex *bssid) -{ - struct registry_priv *pregistrypriv; - struct mlme_ext_priv *pmlmeext; - struct rt_channel_info *chplan_new; - u8 channel; - u8 i; - - pregistrypriv = &padapter->registrypriv; - pmlmeext = &padapter->mlmeextpriv; - - /* Adjust channel plan by AP Country IE */ - if (pregistrypriv->enable80211d && - !pmlmeext->update_channel_plan_by_ap_done) { - const u8 *ie, *p; - struct rt_channel_plan chplan_ap; - struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM]; - u8 country[4]; - u8 fcn; /* first channel number */ - u8 noc; /* number of channel */ - u8 j, k; - - ie = cfg80211_find_ie(WLAN_EID_COUNTRY, bssid->IEs, - bssid->IELength); - if (!ie || ie[1] < IEEE80211_COUNTRY_IE_MIN_LEN) - return; - - p = ie + 2; - ie += ie[1]; - ie += 2; - - memcpy(country, p, 3); - country[3] = '\0'; - - p += 3; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - "%s: 802.11d country =%s\n", __func__, country); - - i = 0; - while ((ie - p) >= 3) { - fcn = *(p++); - noc = *(p++); - p++; - - for (j = 0; j < noc; j++) { - if (fcn <= 14) - channel = fcn + j; /* 2.4 GHz */ - else - channel = fcn + j * 4; /* 5 GHz */ - - chplan_ap.Channel[i++] = channel; - } - } - chplan_ap.Len = i; - - memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta)); - memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set)); - chplan_new = pmlmeext->channel_set; - - i = j = k = 0; - if (pregistrypriv->wireless_mode & WIRELESS_11G) { - do { - if (i == MAX_CHANNEL_NUM || - chplan_sta[i].ChannelNum == 0 || - chplan_sta[i].ChannelNum > 14) - break; - - if (j == chplan_ap.Len || - chplan_ap.Channel[j] > 14) - break; - - if (chplan_sta[i].ChannelNum == - chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = - chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - i++; - j++; - k++; - } else if (chplan_sta[i].ChannelNum < - chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = - chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = - SCAN_PASSIVE; - i++; - k++; - } else if (chplan_sta[i].ChannelNum > - chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = - chplan_ap.Channel[j]; - chplan_new[k].ScanType = - SCAN_ACTIVE; - j++; - k++; - } - } while (1); - - /* change AP not support channel to Passive scan */ - while (i < MAX_CHANNEL_NUM && - chplan_sta[i].ChannelNum != 0 && - chplan_sta[i].ChannelNum <= 14) { - chplan_new[k].ChannelNum = - chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = SCAN_PASSIVE; - i++; - k++; - } - - /* add channel AP supported */ - while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14){ - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } else { - /* keep original STA 2.4G channel plan */ - while (i < MAX_CHANNEL_NUM && - chplan_sta[i].ChannelNum != 0 && - chplan_sta[i].ChannelNum <= 14) { - chplan_new[k].ChannelNum = - chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = chplan_sta[i].ScanType; - i++; - k++; - } - - /* skip AP 2.4G channel plan */ - while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14) - j++; - } - - if (pregistrypriv->wireless_mode & WIRELESS_11A) { - do { - if (i == MAX_CHANNEL_NUM || - chplan_sta[i].ChannelNum == 0) - break; - - if (j == chplan_ap.Len || - chplan_ap.Channel[j] == 0) - break; - - if (chplan_sta[i].ChannelNum == - chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = - chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - i++; - j++; - k++; - } else if (chplan_sta[i].ChannelNum < - chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = - chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = SCAN_PASSIVE; - i++; - k++; - } else if (chplan_sta[i].ChannelNum > - chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = - chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } while (1); - - /* change AP not support channel to Passive scan */ - while (i < MAX_CHANNEL_NUM && - chplan_sta[i].ChannelNum != 0) { - chplan_new[k].ChannelNum = - chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = SCAN_PASSIVE; - i++; - k++; - } - - /* add channel AP supported */ - while (j < chplan_ap.Len && chplan_ap.Channel[j] != 0) { - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } else { - /* keep original STA 5G channel plan */ - while (i < MAX_CHANNEL_NUM && - chplan_sta[i].ChannelNum != 0) { - chplan_new[k].ChannelNum = - chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = chplan_sta[i].ScanType; - i++; - k++; - } - } - pmlmeext->update_channel_plan_by_ap_done = 1; - } - - /* If channel is used by AP, set channel scan type to active */ - channel = bssid->DSConfig; - chplan_new = pmlmeext->channel_set; - i = 0; - while (i < MAX_CHANNEL_NUM && chplan_new[i].ChannelNum != 0) { - if (chplan_new[i].ChannelNum == channel) { - if (chplan_new[i].ScanType == SCAN_PASSIVE) { - /* 5G Bnad 2, 3 (DFS) doesn't change - to active scan */ - if (channel >= 52 && channel <= 144) - break; - - chplan_new[i].ScanType = SCAN_ACTIVE; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, - "%s: change channel %d scan type from passive to active\n", - __func__, channel); - } - break; - } - i++; - } -} - -/**************************************************************************** - -Following are the functions to report events - -*****************************************************************************/ - -void report_survey_event23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct survey_event *psurvey_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext; - struct cmd_priv *pcmdpriv; - - if (!padapter) - return; - - pmlmeext = &padapter->mlmeextpriv; - pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct survey_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - - psurvey_evt->bss = collect_bss_info(padapter, precv_frame); - if (!psurvey_evt->bss) { - kfree(pcmd_obj); - kfree(pevtcmd); - return; - } - - process_80211d(padapter, psurvey_evt->bss); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); - - pmlmeext->sitesurvey_res.bss_cnt++; -} - -void report_surveydone_event23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct surveydone_event *psurveydone_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct surveydone_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt; - - DBG_8723A("survey done event(%x)\n", psurveydone_evt->bss_cnt); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); -} - -void report_join_res23a(struct rtw_adapter *padapter, int res) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct joinbss_event *pjoinbss_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct joinbss_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - memcpy((unsigned char *)&pjoinbss_evt->network.network, - &pmlmeinfo->network, sizeof(struct wlan_bssid_ex)); - pjoinbss_evt->network.join_res = res; - - DBG_8723A("report_join_res23a(%d)\n", res); - - rtw_joinbss_event_prehandle23a(padapter, (u8 *)&pjoinbss_evt->network); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); -} - -void report_del_sta_event23a(struct rtw_adapter *padapter, - unsigned char *MacAddr, unsigned short reason) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct sta_info *psta; - int mac_id; - struct stadel_event *pdel_sta_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct stadel_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - ether_addr_copy((unsigned char *)&pdel_sta_evt->macaddr, MacAddr); - memcpy((unsigned char *)pdel_sta_evt->rsvd, (unsigned char *)&reason, - 2); - - psta = rtw_get_stainfo23a(&padapter->stapriv, MacAddr); - if (psta) - mac_id = (int)psta->mac_id; - else - mac_id = -1; - - pdel_sta_evt->mac_id = mac_id; - - DBG_8723A("report_del_sta_event23a: delete STA, mac_id =%d\n", mac_id); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); -} - -void report_add_sta_event23a(struct rtw_adapter *padapter, - unsigned char *MacAddr, int cam_idx) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct stassoc_event *padd_sta_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!pcmd_obj) - return; - - cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header); - pevtcmd = kzalloc(cmdsz, GFP_ATOMIC); - if (!pevtcmd) { - kfree(pcmd_obj); - return; - } - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct stassoc_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA); - pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); - - padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header)); - ether_addr_copy((unsigned char *)&padd_sta_evt->macaddr, MacAddr); - padd_sta_evt->cam_id = cam_idx; - - DBG_8723A("report_add_sta_event23a: add STA\n"); - - rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj); -} - -/**************************************************************************** - -Following are the event callback functions - -*****************************************************************************/ - -/* for sta/adhoc mode */ -void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - /* ERP */ - VCS_update23a(padapter, psta); - - /* HT */ - if (pmlmepriv->htpriv.ht_option) { - psta->htpriv.ht_option = true; - - psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable; - - if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap)) - psta->htpriv.sgi = true; - - psta->qos_option = true; - - } else { - psta->htpriv.ht_option = false; - - psta->htpriv.ampdu_enable = false; - - psta->htpriv.sgi = false; - psta->qos_option = false; - - } - psta->htpriv.bwmode = pmlmeext->cur_bwmode; - psta->htpriv.ch_offset = pmlmeext->cur_ch_offset; - - psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ - psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ - - /* QoS */ - if (pmlmepriv->qos_option) - psta->qos_option = true; - - psta->state = _FW_LINKED; -} - -void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter, - int join_res) -{ - struct sta_info *psta, *psta_bmc; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (join_res < 0) { - hw_var_set_mlme_join(padapter, 1); - hw_var_set_bssid(padapter, null_addr); - - /* restore to initial setting. */ - update_tx_basic_rate23a(padapter, - padapter->registrypriv.wireless_mode); - - goto exit_mlmeext_joinbss_event_callback23a; - } - - if ((pmlmeinfo->state&0x03) == MSR_ADHOC) { - /* for bc/mc */ - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - if (psta_bmc) { - pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc; - update_bmc_sta_support_rate23a(padapter, psta_bmc->mac_id); - Update_RA_Entry23a(padapter, psta_bmc); - } - } - - /* turn on dynamic functions */ - rtl8723a_odm_support_ability_set(padapter, DYNAMIC_ALL_FUNC_ENABLE); - - /* update IOT-releated issue */ - update_IOT_info23a(padapter); - - HalSetBrateCfg23a(padapter, cur_network->SupportedRates); - - /* BCN interval */ - rtl8723a_set_beacon_interval(padapter, pmlmeinfo->bcn_interval); - - /* update capability */ - update_capinfo23a(padapter, pmlmeinfo->capability); - - /* WMM, Update EDCA param */ - WMMOnAssocRsp23a(padapter); - - /* HT */ - HTOnAssocRsp23a(padapter); - - /* Set cur_channel&cur_bwmode&cur_ch_offset */ - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress); - if (psta) { /* only for infra. mode */ - pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; - - /* DBG_8723A("set_sta_rate23a\n"); */ - - psta->wireless_mode = pmlmeext->cur_wireless_mode; - - /* set per sta rate after updating HT cap. */ - set_sta_rate23a(padapter, psta); - } - - hw_var_set_mlme_join(padapter, 2); - - if ((pmlmeinfo->state&0x03) == MSR_INFRA) { - /* correcting TSF */ - rtw_correct_TSF(padapter); - - /* set_link_timer(pmlmeext, DISCONNECT_TO); */ - } - - rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_CONNECT, 0); - -exit_mlmeext_joinbss_event_callback23a: - DBG_8723A("=>%s\n", __func__); -} - -void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter, - struct sta_info *psta) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - DBG_8723A("%s\n", __func__); - - if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) { - /* adhoc master or sta_count>1 */ - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { - /* nothing to do */ - } else { /* adhoc client */ - /* correcting TSF */ - rtw_correct_TSF(padapter); - - /* start beacon */ - if (send_beacon23a(padapter) != _SUCCESS) { - pmlmeinfo->FW_sta_info[psta->mac_id].status = 0; - - pmlmeinfo->state ^= MSR_ADHOC; - - return; - } - - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - } - hw_var_set_mlme_join(padapter, 2); - } - - pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; - - /* rate radaptive */ - Update_RA_Entry23a(padapter, psta); - - /* update adhoc sta_info */ - update_sta_info23a(padapter, psta); -} - -void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (is_client_associated_to_ap23a(padapter) || - is_IBSS_empty23a(padapter)) { - /* set_opmode_cmd(padapter, infra_client_with_mlme); */ - - hw_var_set_mlme_disconnect(padapter); - hw_var_set_bssid(padapter, null_addr); - - /* restore to initial setting. */ - update_tx_basic_rate23a(padapter, - padapter->registrypriv.wireless_mode); - - /* switch to the 20M Hz mode after disconnect */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, - pmlmeext->cur_bwmode); - - flush_all_cam_entry23a(padapter); - - pmlmeinfo->state = MSR_NOLINK; - - /* set MSR to no link state -> infra. mode */ - rtl8723a_set_media_status(padapter, MSR_INFRA); - - del_timer_sync(&pmlmeext->link_timer); - } -} - -static u8 chk_ap_is_alive(struct rtw_adapter *padapter, struct sta_info *psta) -{ - u8 ret = false; - - if (sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta) && - sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) && - sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)) - ret = false; - else - ret = true; - - sta_update_last_rx_pkts(psta); - return ret; -} - -void linked_status_chk23a(struct rtw_adapter *padapter) -{ - u32 i; - struct sta_info *psta; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (is_client_associated_to_ap23a(padapter)) { - /* linked infrastructure client mode */ - - int tx_chk = _SUCCESS, rx_chk = _SUCCESS; - int rx_chk_limit; - - rx_chk_limit = 4; - - psta = rtw_get_stainfo23a(pstapriv, - pmlmeinfo->network.MacAddress); - if (psta) { - bool is_p2p_enable = false; - - if (chk_ap_is_alive(padapter, psta) == false) - rx_chk = _FAIL; - - if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts) - tx_chk = _FAIL; - - if (pmlmeext->active_keep_alive_check && - (rx_chk == _FAIL || tx_chk == _FAIL)) { - u8 backup_oper_channel = 0; - - /* switch to correct channel of current - network before issue keep-alive frames */ - if (rtw_get_oper_ch23a(padapter) != - pmlmeext->cur_channel) { - backup_oper_channel = - rtw_get_oper_ch23a(padapter); - SelectChannel23a(padapter, - pmlmeext->cur_channel); - } - - if (rx_chk != _SUCCESS) - issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1); - - if ((tx_chk != _SUCCESS && - pmlmeinfo->link_count++ == 0xf) || - rx_chk != _SUCCESS) { - tx_chk = issue_nulldata23a(padapter, - psta->hwaddr, - 0, 3, 1); - /* if tx acked and p2p disabled, - set rx_chk _SUCCESS to reset retry - count */ - if (tx_chk == _SUCCESS && - !is_p2p_enable) - rx_chk = _SUCCESS; - } - - /* back to the original operation channel */ - if (backup_oper_channel>0) - SelectChannel23a(padapter, - backup_oper_channel); - } else { - if (rx_chk != _SUCCESS) { - if (pmlmeext->retry == 0) { - issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress); - issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress); - issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress); - } - } - - if (tx_chk != _SUCCESS && - pmlmeinfo->link_count++ == 0xf) - tx_chk = issue_nulldata23a(padapter, - NULL, 0, 1, - 0); - } - - if (rx_chk == _FAIL) { - pmlmeext->retry++; - if (pmlmeext->retry > rx_chk_limit) { - DBG_8723A_LEVEL(_drv_always_, - "%s(%s): disconnect or " - "roaming\n", __func__, - padapter->pnetdev->name); - receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, - WLAN_REASON_EXPIRATION_CHK); - return; - } - } else - pmlmeext->retry = 0; - - if (tx_chk == _FAIL) - pmlmeinfo->link_count &= 0xf; - else { - pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts; - pmlmeinfo->link_count = 0; - } - - } - } else if (is_client_associated_to_ibss23a(padapter)) { - /* linked IBSS mode */ - /* for each assoc list entry to check the rx pkt counter */ - for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) { - if (pmlmeinfo->FW_sta_info[i].status == 1) { - psta = pmlmeinfo->FW_sta_info[i].psta; - - if (!psta) - continue; - - if (pmlmeinfo->FW_sta_info[i].rx_pkt == - sta_rx_pkts(psta)) { - - if (pmlmeinfo->FW_sta_info[i].retry<3) { - pmlmeinfo->FW_sta_info[i].retry++; - } else { - pmlmeinfo->FW_sta_info[i].retry = 0; - pmlmeinfo->FW_sta_info[i].status = 0; - report_del_sta_event23a(padapter, psta->hwaddr, - 65535/* indicate disconnect caused by no rx */ - ); - } - } else { - pmlmeinfo->FW_sta_info[i].retry = 0; - pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta); - } - } - } - /* set_link_timer(pmlmeext, DISCONNECT_TO); */ - } -} - -static void survey_timer_hdl(unsigned long data) -{ - struct rtw_adapter *padapter = (struct rtw_adapter *)data; - struct cmd_obj *ph2c; - struct sitesurvey_parm *psurveyPara; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - /* issue rtw_sitesurvey_cmd23a */ - if (pmlmeext->sitesurvey_res.state > SCAN_START) { - if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) - pmlmeext->sitesurvey_res.channel_idx++; - - if (pmlmeext->scan_abort == true) { - pmlmeext->sitesurvey_res.channel_idx = - pmlmeext->sitesurvey_res.ch_num; - DBG_8723A("%s idx:%d\n", __func__, - pmlmeext->sitesurvey_res.channel_idx); - - pmlmeext->scan_abort = false;/* reset */ - } - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) - goto exit_survey_timer_hdl; - - psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), - GFP_ATOMIC); - if (!psurveyPara) { - kfree(ph2c); - goto exit_survey_timer_hdl; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, - GEN_CMD_CODE(_SiteSurvey)); - rtw_enqueue_cmd23a(pcmdpriv, ph2c); - } - -exit_survey_timer_hdl: - return; -} - -static void link_timer_hdl(unsigned long data) -{ - struct rtw_adapter *padapter = (struct rtw_adapter *)data; - /* static unsigned int rx_pkt = 0; */ - /* static u64 tx_cnt = 0; */ - /* struct xmit_priv *pxmitpriv = &padapter->xmitpriv; */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - /* struct sta_priv *pstapriv = &padapter->stapriv; */ - - if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { - DBG_8723A("link_timer_hdl:no beacon while connecting\n"); - pmlmeinfo->state = MSR_NOLINK; - report_join_res23a(padapter, -3); - } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) { - /* re-auth timer */ - if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) { - /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */ - /* */ - pmlmeinfo->state = 0; - report_join_res23a(padapter, -1); - return; - /* */ - /* else */ - /* */ - /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */ - /* pmlmeinfo->reauth_count = 0; */ - /* */ - } - - DBG_8723A("link_timer_hdl: auth timeout and try again\n"); - pmlmeinfo->auth_seq = 1; - issue_auth(padapter, NULL, 0); - set_link_timer(pmlmeext, REAUTH_TO); - } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) { - /* re-assoc timer */ - if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) { - pmlmeinfo->state = MSR_NOLINK; - report_join_res23a(padapter, -2); - return; - } - - DBG_8723A("link_timer_hdl: assoc timeout and try again\n"); - issue_assocreq(padapter); - set_link_timer(pmlmeext, REASSOC_TO); - } -} - -static void addba_timer_hdl(unsigned long data) -{ - struct sta_info *psta = (struct sta_info *)data; - struct ht_priv *phtpriv; - - if (!psta) - return; - - phtpriv = &psta->htpriv; - - if (phtpriv->ht_option && phtpriv->ampdu_enable) { - if (phtpriv->candidate_tid_bitmap) - phtpriv->candidate_tid_bitmap = 0x0; - } -} - -void init_addba_retry_timer23a(struct sta_info *psta) -{ - setup_timer(&psta->addba_retry_timer, addba_timer_hdl, - (unsigned long)psta); -} - -void init_mlme_ext_timer23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - setup_timer(&pmlmeext->survey_timer, survey_timer_hdl, - (unsigned long)padapter); - - setup_timer(&pmlmeext->link_timer, link_timer_hdl, - (unsigned long)padapter); -} - -int NULL_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - return H2C_SUCCESS; -} - -int setopmode_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - enum nl80211_iftype type; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - const struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf; - - switch (psetop->mode) { - case NL80211_IFTYPE_P2P_GO: - case NL80211_IFTYPE_AP: - pmlmeinfo->state = MSR_AP; - type = MSR_AP; - break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - /* clear state */ - pmlmeinfo->state &= ~(BIT(0)|BIT(1)); - /* set to STATION_STATE */ - pmlmeinfo->state |= MSR_INFRA; - type = MSR_INFRA; - break; - case NL80211_IFTYPE_ADHOC: - type = MSR_ADHOC; - break; - default: - type = MSR_NOLINK; - break; - } - - hw_var_set_opmode(padapter, type); - /* Set_NETYPE0_MSR(padapter, type); */ - - return H2C_SUCCESS; -} - -int createbss_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf; - /* u32 initialgain; */ - - if (pparm->ifmode == NL80211_IFTYPE_AP || - pparm->ifmode == NL80211_IFTYPE_P2P_GO) { -#ifdef CONFIG_8723AU_AP_MODE - if (pmlmeinfo->state == MSR_AP) { - /* todo: */ - return H2C_SUCCESS; - } -#endif - } - - /* below is for ad-hoc master */ - if (pparm->ifmode == NL80211_IFTYPE_ADHOC) { - rtw_joinbss_reset23a(padapter); - - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pmlmeinfo->ERP_enable = 0; - pmlmeinfo->WMM_enable = 0; - pmlmeinfo->HT_enable = 0; - pmlmeinfo->HT_caps_enable = 0; - pmlmeinfo->HT_info_enable = 0; - - /* disable dynamic functions, such as high power, DIG */ - rtl8723a_odm_support_ability_backup(padapter); - - rtl8723a_odm_support_ability_clr(padapter, - DYNAMIC_FUNC_DISABLE); - - /* cancel link timer */ - del_timer_sync(&pmlmeext->link_timer); - - /* clear CAM */ - flush_all_cam_entry23a(padapter); - - if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ - return H2C_PARAMETERS_ERROR; - - memcpy(pnetwork, pparm, sizeof(struct wlan_bssid_ex)); - - start_create_ibss(padapter); - } - - return H2C_SUCCESS; -} - -int join_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf; - struct ieee80211_ht_operation *pht_info; - u32 i; - u8 *p; - /* u32 initialgain; */ - /* u32 acparm; */ - - /* check already connecting to AP or not */ - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { - if (pmlmeinfo->state & MSR_INFRA) - issue_deauth_ex(padapter, pnetwork->MacAddress, - WLAN_REASON_DEAUTH_LEAVING, 5, 100); - - pmlmeinfo->state = MSR_NOLINK; - - /* clear CAM */ - flush_all_cam_entry23a(padapter); - - del_timer_sync(&pmlmeext->link_timer); - - /* set MSR to nolink -> infra. mode */ - rtl8723a_set_media_status(padapter, MSR_INFRA); - - hw_var_set_mlme_disconnect(padapter); - } - - rtw_joinbss_reset23a(padapter); - - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pmlmeinfo->ERP_enable = 0; - pmlmeinfo->WMM_enable = 0; - pmlmeinfo->HT_enable = 0; - pmlmeinfo->HT_caps_enable = 0; - pmlmeinfo->HT_info_enable = 0; - pmlmeinfo->bwmode_updated = false; - /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */ - - if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ - return H2C_PARAMETERS_ERROR; - - memcpy(pnetwork, pbuf, sizeof(struct wlan_bssid_ex)); - - /* Check AP vendor to move rtw_joinbss_cmd23a() */ - /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pnetwork->IEs, - pnetwork->IELength); */ - - for (i = 0; i < pnetwork->IELength;) { - p = pnetwork->IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */ - if (!memcmp(p + 2, WMM_OUI23A, 4)) - pmlmeinfo->WMM_enable = 1; - break; - - case WLAN_EID_HT_CAPABILITY: /* Get HT Cap IE. */ - pmlmeinfo->HT_caps_enable = 1; - break; - - case WLAN_EID_HT_OPERATION: /* Get HT Info IE. */ - pmlmeinfo->HT_info_enable = 1; - - /* spec case only for cisco's ap because cisco's ap - * issue assoc rsp using mcs rate @40MHz or @20MHz */ - pht_info = (struct ieee80211_ht_operation *)(p + 2); - - if (pregpriv->cbw40_enable && - (pht_info->ht_param & - IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { - /* switch to the 40M Hz mode according to AP */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40; - switch (pht_info->ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - pmlmeext->cur_ch_offset = - HAL_PRIME_CHNL_OFFSET_LOWER; - break; - - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - pmlmeext->cur_ch_offset = - HAL_PRIME_CHNL_OFFSET_UPPER; - break; - - default: - pmlmeext->cur_ch_offset = - HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - - DBG_8723A("set ch/bw before connected\n"); - } - break; - - default: - break; - } - - i += (p[1] + 2); - } - - hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress); - hw_var_set_mlme_join(padapter, 0); - - /* cancel link timer */ - del_timer_sync(&pmlmeext->link_timer); - - start_clnt_join(padapter); - - return H2C_SUCCESS; -} - -int disconnect_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct disconnect_parm *param = (struct disconnect_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; - - if (is_client_associated_to_ap23a(padapter)) { - issue_deauth_ex(padapter, pnetwork->MacAddress, - WLAN_REASON_DEAUTH_LEAVING, - param->deauth_timeout_ms/100, 100); - } - - /* set_opmode_cmd(padapter, infra_client_with_mlme); */ - - /* pmlmeinfo->state = MSR_NOLINK; */ - - hw_var_set_mlme_disconnect(padapter); - hw_var_set_bssid(padapter, null_addr); - - /* restore to initial setting. */ - update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode); - - if ((pmlmeinfo->state & 0x03) == MSR_ADHOC || - (pmlmeinfo->state & 0x03) == MSR_AP) - rtl8723a_set_bcn_func(padapter, 0); /* Stop BCN */ - - /* set MSR to no link state -> infra. mode */ - rtl8723a_set_media_status(padapter, MSR_INFRA); - - pmlmeinfo->state = MSR_NOLINK; - - /* switch to the 20M Hz mode after disconnect */ - pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - flush_all_cam_entry23a(padapter); - - del_timer_sync(&pmlmeext->link_timer); - - rtw_free_uc_swdec_pending_queue23a(padapter); - - return H2C_SUCCESS; -} - -static int -rtw_scan_ch_decision(struct rtw_adapter *padapter, - struct rtw_ieee80211_channel *out, u32 out_num, - const struct rtw_ieee80211_channel *in, u32 in_num) -{ - int i, j; - int scan_ch_num = 0; - int set_idx; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - /* clear out first */ - memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num); - - /* acquire channels from in */ - j = 0; - for (i = 0;i<in_num;i++) { - if (in[i].hw_value && - !(in[i].flags & IEEE80211_CHAN_DISABLED) && - (set_idx = rtw_ch_set_search_ch23a(pmlmeext->channel_set, - in[i].hw_value)) >= 0) { - memcpy(&out[j], &in[i], - sizeof(struct rtw_ieee80211_channel)); - - if (pmlmeext->channel_set[set_idx].ScanType == - SCAN_PASSIVE) - out[j].flags &= IEEE80211_CHAN_NO_IR; - - j++; - } - if (j>= out_num) - break; - } - - /* if out is empty, use channel_set as default */ - if (j == 0) { - for (i = 0;i<pmlmeext->max_chan_nums;i++) { - out[i].hw_value = pmlmeext->channel_set[i].ChannelNum; - - if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE) - out[i].flags &= IEEE80211_CHAN_NO_IR; - - j++; - } - } - - if (padapter->setband == GHZ_24) { /* 2.4G */ - for (i = 0; i < j ; i++) { - if (out[i].hw_value > 35) - memset(&out[i], 0, - sizeof(struct rtw_ieee80211_channel)); - else - scan_ch_num++; - } - j = scan_ch_num; - } else if (padapter->setband == GHZ_50) { /* 5G */ - for (i = 0; i < j ; i++) { - if (out[i].hw_value > 35) { - memcpy(&out[scan_ch_num++], &out[i], - sizeof(struct rtw_ieee80211_channel)); - } - } - j = scan_ch_num; - } else - {} - - return j; -} - -int sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - const struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf; - u8 bdelayscan = false; - u32 initialgain; - u32 i; - - if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) { - pmlmeext->sitesurvey_res.state = SCAN_START; - pmlmeext->sitesurvey_res.bss_cnt = 0; - pmlmeext->sitesurvey_res.channel_idx = 0; - - for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { - if (pparm->ssid[i].ssid_len) { - memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid, - pparm->ssid[i].ssid, - IEEE80211_MAX_SSID_LEN); - pmlmeext->sitesurvey_res.ssid[i].ssid_len = - pparm->ssid[i].ssid_len; - } else { - pmlmeext->sitesurvey_res.ssid[i].ssid_len = 0; - } - } - - pmlmeext->sitesurvey_res.ch_num = - rtw_scan_ch_decision(padapter, - pmlmeext->sitesurvey_res.ch, - RTW_CHANNEL_SCAN_AMOUNT, - pparm->ch, pparm->ch_num); - - pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode; - - /* issue null data if associating to the AP */ - if (is_client_associated_to_ap23a(padapter)) { - pmlmeext->sitesurvey_res.state = SCAN_TXNULL; - - /* switch to correct channel of current network - before issue keep-alive frames */ - if (rtw_get_oper_ch23a(padapter) != - pmlmeext->cur_channel) - SelectChannel23a(padapter, - pmlmeext->cur_channel); - - issue_nulldata23a(padapter, NULL, 1, 3, 500); - - bdelayscan = true; - } - - if (bdelayscan) { - /* delay 50ms to protect nulldata(1). */ - set_survey_timer(pmlmeext, 50); - return H2C_SUCCESS; - } - } - - if (pmlmeext->sitesurvey_res.state == SCAN_START || - pmlmeext->sitesurvey_res.state == SCAN_TXNULL) { - /* disable dynamic functions, such as high power, DIG */ - rtl8723a_odm_support_ability_backup(padapter); - rtl8723a_odm_support_ability_clr(padapter, - DYNAMIC_FUNC_DISABLE); - - /* config the initial gain under scanning, need to - write the BB registers */ - if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == true) - initialgain = 0x30; - else - initialgain = 0x1E; - - rtl8723a_set_initial_gain(padapter, initialgain); - - /* set MSR to no link state */ - rtl8723a_set_media_status(padapter, MSR_NOLINK); - - rtl8723a_mlme_sitesurvey(padapter, 1); - - pmlmeext->sitesurvey_res.state = SCAN_PROCESS; - } - - rtw_site_survey(padapter); - - return H2C_SUCCESS; -} - -int setauth_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct setauth_parm *pparm = (struct setauth_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pparm->mode < 4) - pmlmeinfo->auth_algo = pparm->mode; - - return H2C_SUCCESS; -} - -int setkey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - unsigned short ctrl; - const struct setkey_parm *pparm = (struct setkey_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - /* main tx key for wep. */ - if (pparm->set_tx) - pmlmeinfo->key_index = pparm->keyid; - - /* write cam */ - ctrl = BIT(15) | (pparm->algorithm) << 2 | pparm->keyid; - - DBG_8723A_LEVEL(_drv_always_, "set group key to hw: alg:%d(WEP40-1 " - "WEP104-5 TKIP-2 AES-4) keyid:%d\n", - pparm->algorithm, pparm->keyid); - rtl8723a_cam_write(padapter, pparm->keyid, ctrl, null_sta, pparm->key); - - /* allow multicast packets to driver */ - rtl8723a_on_rcr_am(padapter); - - return H2C_SUCCESS; -} - -int set_stakey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - u16 ctrl = 0; - u8 cam_id;/* cam_entry */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - const struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf; - - /* cam_entry: */ - /* 0~3 for default key */ - - /* for concurrent mode (ap+sta): */ - /* default key is disable, using sw encrypt/decrypt */ - /* cam_entry = 4 for sta mode (macid = 0) */ - /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */ - - /* for concurrent mode (sta+sta): */ - /* default key is disable, using sw encrypt/decrypt */ - /* cam_entry = 4 mapping to macid = 0 */ - /* cam_entry = 5 mapping to macid = 2 */ - - cam_id = 4; - - DBG_8723A_LEVEL(_drv_always_, "set pairwise key to hw: alg:%d(WEP40-1 " - "WEP104-5 TKIP-2 AES-4) camid:%d\n", - pparm->algorithm, cam_id); - if ((pmlmeinfo->state & 0x03) == MSR_AP) { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (pparm->algorithm == 0) { /* clear cam entry */ - clear_cam_entry23a(padapter, pparm->id); - return H2C_SUCCESS_RSP; - } - - psta = rtw_get_stainfo23a(pstapriv, pparm->addr); - if (psta) { - ctrl = BIT(15) | (pparm->algorithm << 2); - - DBG_8723A("r871x_set_stakey_hdl23a(): enc_algorithm " - "=%d\n", pparm->algorithm); - - if (psta->mac_id < 1 || psta->mac_id > (NUM_STA - 4)) { - DBG_8723A("r871x_set_stakey_hdl23a():set_stakey" - " failed, mac_id(aid) =%d\n", - psta->mac_id); - return H2C_REJECTED; - } - - /* 0~3 for default key, cmd_id = macid + 3, - macid = aid+1; */ - cam_id = psta->mac_id + 3; - - DBG_8723A("Write CAM, mac_addr =%pM, " - "cam_entry =%d\n", pparm->addr, cam_id); - - rtl8723a_cam_write(padapter, cam_id, ctrl, - pparm->addr, pparm->key); - - return H2C_SUCCESS_RSP; - } else { - DBG_8723A("r871x_set_stakey_hdl23a(): sta has been " - "free\n"); - return H2C_REJECTED; - } - } - - /* below for sta mode */ - - if (pparm->algorithm == 0) { /* clear cam entry */ - clear_cam_entry23a(padapter, pparm->id); - return H2C_SUCCESS; - } - - ctrl = BIT(15) | (pparm->algorithm << 2); - - rtl8723a_cam_write(padapter, cam_id, ctrl, pparm->addr, pparm->key); - - pmlmeinfo->enc_algo = pparm->algorithm; - - return H2C_SUCCESS; -} - -int add_ba_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sta_info *psta; - - psta = rtw_get_stainfo23a(&padapter->stapriv, pparm->addr); - - if (!psta) - return H2C_SUCCESS; - - if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && - pmlmeinfo->HT_enable) || - (pmlmeinfo->state & 0x03) == MSR_AP) { - issue_action_BA23a(padapter, pparm->addr, - WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid); - mod_timer(&psta->addba_retry_timer, - jiffies + msecs_to_jiffies(ADDBA_TO)); - } else - psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid); - - return H2C_SUCCESS; -} - -int set_tx_beacon_cmd23a(struct rtw_adapter *padapter) -{ - struct cmd_obj *ph2c; - struct Tx_Beacon_param *ptxBeacon_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u8 res = _SUCCESS; - int len_diff = 0; - - ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC); - if (!ph2c) { - res = _FAIL; - goto exit; - } - - ptxBeacon_parm = kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC); - if (!ptxBeacon_parm) { - kfree(ph2c); - res = _FAIL; - goto exit; - } - - memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network, - sizeof(struct wlan_bssid_ex)); - - len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs, - ptxBeacon_parm->network.IELength, - pmlmeinfo->hidden_ssid_mode); - ptxBeacon_parm->network.IELength += len_diff; - - init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, - GEN_CMD_CODE(_TX_Beacon)); - - res = rtw_enqueue_cmd23a(pcmdpriv, ph2c); - -exit: - return res; -} - -int mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - u8 evt_code, evt_seq; - u16 evt_sz; - const struct C2HEvent_Header *c2h; - void (*event_callback)(struct rtw_adapter *dev, const u8 *pbuf); - - c2h = (struct C2HEvent_Header *)pbuf; - evt_sz = c2h->len; - evt_seq = c2h->seq; - evt_code = c2h->ID; - - /* checking if event code is valid */ - if (evt_code >= MAX_C2HEVT) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "Event Code(%d) mismatch!\n", evt_code); - goto _abort_event_; - } - - /* checking if event size match the event parm size */ - if (wlanevents[evt_code].parmsize != 0 && - wlanevents[evt_code].parmsize != evt_sz) { - RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, - "Event(%d) Parm Size mismatch (%d vs %d)!\n", - evt_code, wlanevents[evt_code].parmsize, evt_sz); - goto _abort_event_; - } - - event_callback = wlanevents[evt_code].event_callback; - event_callback(padapter, pbuf + sizeof(struct C2HEvent_Header)); - -_abort_event_: - - return H2C_SUCCESS; -} - -int h2c_msg_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - return H2C_SUCCESS; -} - -int tx_beacon_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - if (send_beacon23a(padapter) == _FAIL) { - DBG_8723A("issue_beacon23a, fail!\n"); - return H2C_PARAMETERS_ERROR; - } -#ifdef CONFIG_8723AU_AP_MODE - else { /* tx bc/mc frames after update TIM */ - struct sta_info *psta_bmc; - struct list_head *phead; - struct xmit_frame *pxmitframe, *ptmp; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - if (!psta_bmc) - return H2C_SUCCESS; - - if (pstapriv->tim_bitmap & BIT(0) && psta_bmc->sleepq_len > 0) { - msleep(10);/* 10ms, ATIM(HIQ) Windows */ - /* spin_lock_bh(&psta_bmc->sleep_q.lock); */ - spin_lock_bh(&pxmitpriv->lock); - - phead = get_list_head(&psta_bmc->sleep_q); - - list_for_each_entry_safe(pxmitframe, ptmp, - phead, list) { - - list_del_init(&pxmitframe->list); - - psta_bmc->sleepq_len--; - if (psta_bmc->sleepq_len>0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - - pxmitframe->attrib.qsel = 0x11;/* HIQ */ - - rtl8723au_hal_xmitframe_enqueue(padapter, - pxmitframe); - } - /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */ - spin_unlock_bh(&pxmitpriv->lock); - } - } -#endif - - return H2C_SUCCESS; -} - -int set_ch_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct set_ch_parm *set_ch_parm; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - set_ch_parm = (struct set_ch_parm *)pbuf; - - DBG_8723A("%s(%s): ch:%u, bw:%u, ch_offset:%u\n", __func__, - padapter->pnetdev->name, set_ch_parm->ch, - set_ch_parm->bw, set_ch_parm->ch_offset); - - pmlmeext->cur_channel = set_ch_parm->ch; - pmlmeext->cur_ch_offset = set_ch_parm->ch_offset; - pmlmeext->cur_bwmode = set_ch_parm->bw; - - set_channel_bwmode23a(padapter, set_ch_parm->ch, - set_ch_parm->ch_offset, set_ch_parm->bw); - - return H2C_SUCCESS; -} - -int set_chplan_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - const struct SetChannelPlan_param *setChannelPlan_param; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - setChannelPlan_param = (struct SetChannelPlan_param *)pbuf; - - pmlmeext->max_chan_nums = - init_channel_set(padapter, setChannelPlan_param->channel_plan, - pmlmeext->channel_set); - init_channel_list(padapter, pmlmeext->channel_set, - pmlmeext->max_chan_nums, &pmlmeext->channel_list); - - return H2C_SUCCESS; -} - -int led_blink_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - struct LedBlink_param *ledBlink_param; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - ledBlink_param = (struct LedBlink_param *)pbuf; - - return H2C_SUCCESS; -} - -int set_csa_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - return H2C_REJECTED; -} - -/* TDLS_WRCR : write RCR DATA BIT */ -/* TDLS_SD_PTI : issue peer traffic indication */ -/* TDLS_CS_OFF : go back to the channel linked with AP, - terminating channel switch procedure */ -/* TDLS_INIT_CH_SEN : init channel sensing, receive all data and - mgnt frame */ -/* TDLS_DONE_CH_SEN : channel sensing and report candidate channel */ -/* TDLS_OFF_CH : first time set channel to off channel */ -/* TDLS_BASE_CH : go back tp the channel linked with AP when set - base channel as target channel */ -/* TDLS_P_OFF_CH : periodically go to off channel */ -/* TDLS_P_BASE_CH : periodically go back to base channel */ -/* TDLS_RS_RCR : restore RCR */ -/* TDLS_CKALV_PH1 : check alive timer phase1 */ -/* TDLS_CKALV_PH2 : check alive timer phase2 */ -/* TDLS_FREE_STA : free tdls sta */ -int tdls_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf) -{ - return H2C_REJECTED; -} diff --git a/drivers/staging/rtl8723au/core/rtw_pwrctrl.c b/drivers/staging/rtl8723au/core/rtw_pwrctrl.c deleted file mode 100644 index 7488a104935b..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_pwrctrl.c +++ /dev/null @@ -1,606 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_PWRCTRL_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <osdep_intf.h> -#include <rtl8723a_cmd.h> -#include <rtw_sreset.h> - -#include <rtl8723a_bt_intf.h> -#include <usb_ops_linux.h> - -void ips_enter23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - down(&pwrpriv->lock); - - pwrpriv->bips_processing = true; - - /* syn ips_mode with request */ - pwrpriv->ips_mode = pwrpriv->ips_mode_req; - - pwrpriv->ips_enter23a_cnts++; - DBG_8723A("==>ips_enter23a cnts:%d\n", pwrpriv->ips_enter23a_cnts); - rtl8723a_BT_disable_coexist(padapter); - - if (pwrpriv->change_rfpwrstate == rf_off) { - pwrpriv->bpower_saving = true; - DBG_8723A_LEVEL(_drv_always_, "nolinked power save enter\n"); - - if (pwrpriv->ips_mode == IPS_LEVEL_2) - pwrpriv->bkeepfwalive = true; - - rtw_ips_pwr_down23a(padapter); - pwrpriv->rf_pwrstate = rf_off; - } - pwrpriv->bips_processing = false; - - up(&pwrpriv->lock); -} - -int ips_leave23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int result = _SUCCESS; - int keyid; - - down(&pwrpriv->lock); - - if (pwrpriv->rf_pwrstate == rf_off && !pwrpriv->bips_processing) { - pwrpriv->bips_processing = true; - pwrpriv->change_rfpwrstate = rf_on; - pwrpriv->ips_leave23a_cnts++; - DBG_8723A("==>ips_leave23a cnts:%d\n", - pwrpriv->ips_leave23a_cnts); - - result = rtw_ips_pwr_up23a(padapter); - if (result == _SUCCESS) - pwrpriv->rf_pwrstate = rf_on; - - DBG_8723A_LEVEL(_drv_always_, "nolinked power save leave\n"); - - if (psecuritypriv->dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_WEP40 || - psecuritypriv->dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_WEP104) { - DBG_8723A("==>%s, channel(%d), processing(%x)\n", - __func__, padapter->mlmeextpriv.cur_channel, - pwrpriv->bips_processing); - set_channel_bwmode23a(padapter, - padapter->mlmeextpriv.cur_channel, - HAL_PRIME_CHNL_OFFSET_DONT_CARE, - HT_CHANNEL_WIDTH_20); - for (keyid = 0; keyid < 4; keyid++) { - if (pmlmepriv->key_mask & BIT(keyid)) { - if (keyid == - psecuritypriv->dot11PrivacyKeyIndex) - result = rtw_set_key23a(padapter, psecuritypriv, keyid, 1); - else - result = rtw_set_key23a(padapter, psecuritypriv, keyid, 0); - } - } - } - - DBG_8723A("==> ips_leave23a.....LED(0x%08x)...\n", - rtl8723au_read32(padapter, 0x4c)); - pwrpriv->bips_processing = false; - - pwrpriv->bkeepfwalive = false; - pwrpriv->bpower_saving = false; - } - - up(&pwrpriv->lock); - - return result; -} - - -static bool rtw_pwr_unassociated_idle(struct rtw_adapter *adapter) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct xmit_priv *pxmit_priv = &adapter->xmitpriv; - - bool ret = false; - - if (time_after_eq(adapter->pwrctrlpriv.ips_deny_time, jiffies)) - goto exit; - - if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR) || - check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS) || - check_fwstate(pmlmepriv, WIFI_AP_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)){ - goto exit; - } - - if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF || - pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) { - DBG_8723A_LEVEL(_drv_always_, - "There are some pkts to transmit\n"); - DBG_8723A_LEVEL(_drv_info_, "free_xmitbuf_cnt: %d, " - "free_xmit_extbuf_cnt: %d\n", - pxmit_priv->free_xmitbuf_cnt, - pxmit_priv->free_xmit_extbuf_cnt); - goto exit; - } - - ret = true; - -exit: - return ret; -} - -void rtw_ps_processor23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pwrpriv->ps_processing = true; - - if (pwrpriv->bips_processing == true) - goto exit; - - if (pwrpriv->ips_mode_req == IPS_NONE) - goto exit; - - if (!rtw_pwr_unassociated_idle(padapter)) - goto exit; - - if (pwrpriv->rf_pwrstate == rf_on && - (pwrpriv->pwr_state_check_cnts % 4) == 0) { - DBG_8723A("==>%s .fw_state(%x)\n", __func__, - get_fwstate(pmlmepriv)); - pwrpriv->change_rfpwrstate = rf_off; - ips_enter23a(padapter); - } -exit: - rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv); - pwrpriv->ps_processing = false; -} - -static void pwr_state_check_handler(unsigned long data) -{ - struct rtw_adapter *padapter = (struct rtw_adapter *)data; - - rtw_ps_cmd23a(padapter); -} - -/* - * - * Parameters - * padapter - * pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4 - * - */ -void rtw_set_rpwm23a(struct rtw_adapter *padapter, u8 pslv) -{ - u8 rpwm; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - pslv = PS_STATE(pslv); - - if (pwrpriv->btcoex_rfon) { - if (pslv < PS_STATE_S4) - pslv = PS_STATE_S3; - } - - if (pwrpriv->rpwm == pslv) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, - "%s: Already set rpwm[0x%02X], new = 0x%02X!\n", - __func__, pwrpriv->rpwm, pslv); - return; - } - - if (padapter->bSurpriseRemoved == true || - padapter->hw_init_completed == false) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, - "%s: SurpriseRemoved(%d) hw_init_completed(%d)\n", - __func__, padapter->bSurpriseRemoved, - padapter->hw_init_completed); - - pwrpriv->cpwm = PS_STATE_S4; - - return; - } - - if (padapter->bDriverStopped == true) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, - "%s: change power state(0x%02X) when DriverStopped\n", - __func__, pslv); - - if (pslv < PS_STATE_S2) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, - "%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", - __func__, pslv); - return; - } - } - - rpwm = pslv | pwrpriv->tog; - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, - "rtw_set_rpwm23a: rpwm = 0x%02x cpwm = 0x%02x\n", - rpwm, pwrpriv->cpwm); - - pwrpriv->rpwm = pslv; - - rtl8723a_set_rpwm(padapter, rpwm); - - pwrpriv->tog += 0x80; - pwrpriv->cpwm = pslv; -} - -static bool PS_RDY_CHECK(struct rtw_adapter *padapter) -{ - unsigned long delta_time; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - delta_time = jiffies - pwrpriv->DelayLPSLastTimeStamp; - - if (delta_time < LPS_DELAY_TIME) - return false; - - if (!check_fwstate(pmlmepriv, _FW_LINKED) || - check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) || - check_fwstate(pmlmepriv, WIFI_AP_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) - return false; - if (pwrpriv->bInSuspend) - return false; - if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && - !padapter->securitypriv.binstallGrpkey) { - DBG_8723A("Group handshake still in progress !!!\n"); - return false; - } - if (!rtw_cfg80211_pwr_mgmt(padapter)) - return false; - - return true; -} - -void rtw_set_ps_mode23a(struct rtw_adapter *padapter, u8 ps_mode, - u8 smart_ps, u8 bcn_ant_mode) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, - "%s: PowerMode =%d Smart_PS =%d\n", - __func__, ps_mode, smart_ps); - - if (ps_mode > PM_Card_Disable) { - RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, - "ps_mode:%d error\n", ps_mode); - return; - } - - if (pwrpriv->pwr_mode == ps_mode) { - if (PS_MODE_ACTIVE == ps_mode) - return; - - if (pwrpriv->smart_ps == smart_ps && - pwrpriv->bcn_ant_mode == bcn_ant_mode) - return; - } - - if (ps_mode == PS_MODE_ACTIVE) { - DBG_8723A("rtw_set_ps_mode23a: Leave 802.11 power save\n"); - - pwrpriv->pwr_mode = ps_mode; - rtw_set_rpwm23a(padapter, PS_STATE_S4); - rtl8723a_set_FwPwrMode_cmd(padapter, ps_mode); - pwrpriv->bFwCurrentInPSMode = false; - } else { - if (PS_RDY_CHECK(padapter) || - rtl8723a_BT_using_antenna_1(padapter)) { - DBG_8723A("%s: Enter 802.11 power save\n", __func__); - - pwrpriv->bFwCurrentInPSMode = true; - pwrpriv->pwr_mode = ps_mode; - pwrpriv->smart_ps = smart_ps; - pwrpriv->bcn_ant_mode = bcn_ant_mode; - rtl8723a_set_FwPwrMode_cmd(padapter, ps_mode); - - rtw_set_rpwm23a(padapter, PS_STATE_S2); - } - } -} - -/* - * Return: - * 0: Leave OK - * -1: Timeout - * -2: Other error - */ -s32 LPS_RF_ON_check23a(struct rtw_adapter *padapter, u32 delay_ms) -{ - unsigned long start_time, end_time; - u8 bAwake = false; - s32 err = 0; - - start_time = jiffies; - end_time = start_time + msecs_to_jiffies(delay_ms); - - while (1) { - bAwake = rtl8723a_get_fwlps_rf_on(padapter); - if (bAwake == true) - break; - - if (padapter->bSurpriseRemoved == true) { - err = -2; - DBG_8723A("%s: device surprise removed!!\n", __func__); - break; - } - - if (time_after(jiffies, end_time)) { - err = -1; - DBG_8723A("%s: Wait for FW LPS leave more than %u " - "ms!\n", __func__, delay_ms); - break; - } - udelay(100); - } - - return err; -} - -/* Description: */ -/* Enter the leisure power save mode. */ -void LPS_Enter23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - if (!PS_RDY_CHECK(padapter)) - return; - - if (pwrpriv->bLeisurePs) { - /* Idle for a while if we connect to AP a while ago. */ - if (pwrpriv->LpsIdleCount >= 2) { /* 4 Sec */ - if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) { - pwrpriv->bpower_saving = true; - DBG_8723A("%s smart_ps:%d\n", __func__, - pwrpriv->smart_ps); - /* For Tenda W311R IOT issue */ - rtw_set_ps_mode23a(padapter, - pwrpriv->power_mgnt, - pwrpriv->smart_ps, 0); - } - } else - pwrpriv->LpsIdleCount++; - } -} - -/* Description: */ -/* Leave the leisure power save mode. */ -void LPS_Leave23a(struct rtw_adapter *padapter) -{ -#define LPS_LEAVE_TIMEOUT_MS 100 - - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - if (pwrpriv->bLeisurePs) { - if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) { - rtw_set_ps_mode23a(padapter, PS_MODE_ACTIVE, 0, 0); - - if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) - LPS_RF_ON_check23a(padapter, - LPS_LEAVE_TIMEOUT_MS); - } - } - - pwrpriv->bpower_saving = false; -} - -/* Description: Leave all power save mode: LPS, FwLPS, IPS if needed. */ -/* Move code to function by tynli. 2010.03.26. */ -void LeaveAllPowerSaveMode23a(struct rtw_adapter *Adapter) -{ - struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; - u8 enqueue = 0; - - /* DBG_8723A("%s.....\n", __func__); */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) - rtw_lps_ctrl_wk_cmd23a(Adapter, LPS_CTRL_LEAVE, enqueue); -} - -void rtw_init_pwrctrl_priv23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - sema_init(&pwrctrlpriv->lock, 1); - pwrctrlpriv->rf_pwrstate = rf_on; - pwrctrlpriv->ips_enter23a_cnts = 0; - pwrctrlpriv->ips_leave23a_cnts = 0; - pwrctrlpriv->bips_processing = false; - - pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode; - pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode; - - pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL; - pwrctrlpriv->pwr_state_check_cnts = 0; - pwrctrlpriv->bInSuspend = false; - pwrctrlpriv->bkeepfwalive = false; - - pwrctrlpriv->LpsIdleCount = 0; - - /* PS_MODE_MIN; */ - pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt; - pwrctrlpriv->bLeisurePs = - (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?true:false; - - pwrctrlpriv->bFwCurrentInPSMode = false; - - pwrctrlpriv->rpwm = 0; - pwrctrlpriv->cpwm = PS_STATE_S4; - - pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE; - pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps; - pwrctrlpriv->bcn_ant_mode = 0; - - pwrctrlpriv->tog = 0x80; - - pwrctrlpriv->btcoex_rfon = false; - - setup_timer(&pwrctrlpriv->pwr_state_check_timer, - pwr_state_check_handler, (unsigned long)padapter); -} - -void rtw_free_pwrctrl_priv(struct rtw_adapter *adapter) -{ -} - -inline void rtw_set_ips_deny23a(struct rtw_adapter *padapter, u32 ms) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ms); -} - -/* -* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend -* @adapter: pointer to _adapter structure -* @ips_deffer_ms: the ms will prevent from falling into IPS after wakeup -* Return _SUCCESS or _FAIL -*/ - -int _rtw_pwr_wakeup23a(struct rtw_adapter *padapter, u32 ips_deffer_ms, const char *caller) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int ret = _SUCCESS; - unsigned long start = jiffies; - unsigned long new_deny_time; - - new_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms); - - if (time_before(pwrpriv->ips_deny_time, new_deny_time)) - pwrpriv->ips_deny_time = new_deny_time; - - if (pwrpriv->ps_processing) { - DBG_8723A("%s wait ps_processing...\n", __func__); - while (pwrpriv->ps_processing && - jiffies_to_msecs(jiffies - start) <= 3000) - msleep(10); - if (pwrpriv->ps_processing) - DBG_8723A("%s wait ps_processing timeout\n", __func__); - else - DBG_8723A("%s wait ps_processing done\n", __func__); - } - - if (rtw_sreset_inprogress(padapter)) { - DBG_8723A("%s wait sreset_inprogress...\n", __func__); - while (rtw_sreset_inprogress(padapter) && - jiffies_to_msecs(jiffies - start) <= 4000) - msleep(10); - if (rtw_sreset_inprogress(padapter)) - DBG_8723A("%s wait sreset_inprogress timeout\n", - __func__); - else - DBG_8723A("%s wait sreset_inprogress done\n", __func__); - } - - if (pwrpriv->bInSuspend) { - DBG_8723A("%s wait bInSuspend...\n", __func__); - while (pwrpriv->bInSuspend && - (jiffies_to_msecs(jiffies - start) <= 3000)) { - msleep(10); - } - if (pwrpriv->bInSuspend) - DBG_8723A("%s wait bInSuspend timeout\n", __func__); - else - DBG_8723A("%s wait bInSuspend done\n", __func__); - } - - /* System suspend is not allowed to wakeup */ - if (pwrpriv->bInSuspend) { - ret = _FAIL; - goto exit; - } - - /* I think this should be check in IPS, LPS, autosuspend functions... */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - ret = _SUCCESS; - goto exit; - } - - if (rf_off == pwrpriv->rf_pwrstate) { - DBG_8723A("%s call ips_leave23a....\n", __func__); - if (ips_leave23a(padapter)== _FAIL) { - DBG_8723A("======> ips_leave23a fail.............\n"); - ret = _FAIL; - goto exit; - } - } - - /* TODO: the following checking need to be merged... */ - if (padapter->bDriverStopped || !padapter->bup || - !padapter->hw_init_completed) { - DBG_8723A("%s: bDriverStopped =%d, bup =%d, hw_init_completed " - "=%u\n", caller, padapter->bDriverStopped, - padapter->bup, padapter->hw_init_completed); - ret = _FAIL; - goto exit; - } - -exit: - new_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms); - if (time_before(pwrpriv->ips_deny_time, new_deny_time)) - pwrpriv->ips_deny_time = new_deny_time; - return ret; -} - -int rtw_pm_set_lps23a(struct rtw_adapter *padapter, u8 mode) -{ - int ret = 0; - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - if (mode < PS_MODE_NUM) { - if (pwrctrlpriv->power_mgnt != mode) { - if (PS_MODE_ACTIVE == mode) - LeaveAllPowerSaveMode23a(padapter); - else - pwrctrlpriv->LpsIdleCount = 2; - pwrctrlpriv->power_mgnt = mode; - pwrctrlpriv->bLeisurePs = - (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt) ? - true:false; - } - } else - ret = -EINVAL; - - return ret; -} - -int rtw_pm_set_ips23a(struct rtw_adapter *padapter, u8 mode) -{ - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - if (mode != IPS_NORMAL && mode != IPS_LEVEL_2 && mode != IPS_NONE) - return -EINVAL; - - pwrctrlpriv->ips_mode_req = mode; - if (mode == IPS_NONE) { - DBG_8723A("%s %s\n", __func__, "IPS_NONE"); - if (padapter->bSurpriseRemoved == 0 && - rtw_pwr_wakeup(padapter) == _FAIL) - return -EFAULT; - } - - return 0; -} diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c b/drivers/staging/rtl8723au/core/rtw_recv.c deleted file mode 100644 index 150dabc2a58d..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_recv.c +++ /dev/null @@ -1,2204 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_RECV_C_ -#include <osdep_service.h> -#include <drv_types.h> -#include <recv_osdep.h> -#include <mlme_osdep.h> -#include <linux/ip.h> -#include <linux/if_ether.h> -#include <usb_ops.h> -#include <linux/ieee80211.h> -#include <wifi.h> -#include <rtl8723a_recv.h> -#include <rtl8723a_xmit.h> - -void rtw_signal_stat_timer_hdl23a(unsigned long data); - -void _rtw_init_sta_recv_priv23a(struct sta_recv_priv *psta_recvpriv) -{ - - - - spin_lock_init(&psta_recvpriv->lock); - - /* for (i = 0; i<MAX_RX_NUMBLKS; i++) */ - /* _rtw_init_queue23a(&psta_recvpriv->blk_strms[i]); */ - - _rtw_init_queue23a(&psta_recvpriv->defrag_q); - - -} - -int _rtw_init_recv_priv23a(struct recv_priv *precvpriv, - struct rtw_adapter *padapter) -{ - struct recv_frame *precvframe; - int i; - int res = _SUCCESS; - - spin_lock_init(&precvpriv->lock); - - _rtw_init_queue23a(&precvpriv->free_recv_queue); - _rtw_init_queue23a(&precvpriv->recv_pending_queue); - _rtw_init_queue23a(&precvpriv->uc_swdec_pending_queue); - - precvpriv->adapter = padapter; - - for (i = 0; i < NR_RECVFRAME ; i++) { - precvframe = kzalloc(sizeof(struct recv_frame), GFP_KERNEL); - if (!precvframe) - break; - INIT_LIST_HEAD(&precvframe->list); - - list_add_tail(&precvframe->list, - &precvpriv->free_recv_queue.queue); - - precvframe->adapter = padapter; - precvframe++; - } - - precvpriv->free_recvframe_cnt = i; - precvpriv->rx_pending_cnt = 1; - - res = rtl8723au_init_recv_priv(padapter); - - setup_timer(&precvpriv->signal_stat_timer, rtw_signal_stat_timer_hdl23a, - (unsigned long)padapter); - - precvpriv->signal_stat_sampling_interval = 1000; /* ms */ - - rtw_set_signal_stat_timer(precvpriv); - - return res; -} - -void _rtw_free_recv_priv23a(struct recv_priv *precvpriv) -{ - struct rtw_adapter *padapter = precvpriv->adapter; - struct recv_frame *precvframe, *ptmp; - - rtw_free_uc_swdec_pending_queue23a(padapter); - - list_for_each_entry_safe(precvframe, ptmp, - &precvpriv->free_recv_queue.queue, list) { - list_del_init(&precvframe->list); - kfree(precvframe); - } - - rtl8723au_free_recv_priv(padapter); -} - -struct recv_frame *rtw_alloc_recvframe23a(struct rtw_queue *pfree_recv_queue) -{ - struct recv_frame *pframe; - struct rtw_adapter *padapter; - struct recv_priv *precvpriv; - - spin_lock_bh(&pfree_recv_queue->lock); - - pframe = list_first_entry_or_null(&pfree_recv_queue->queue, - struct recv_frame, list); - if (pframe) { - list_del_init(&pframe->list); - padapter = pframe->adapter; - if (padapter) { - precvpriv = &padapter->recvpriv; - if (pfree_recv_queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt--; - } - } - - spin_unlock_bh(&pfree_recv_queue->lock); - - return pframe; -} - -int rtw_free_recvframe23a(struct recv_frame *precvframe) -{ - struct rtw_adapter *padapter = precvframe->adapter; - struct recv_priv *precvpriv = &padapter->recvpriv; - struct rtw_queue *pfree_recv_queue; - - if (precvframe->pkt) { - dev_kfree_skb_any(precvframe->pkt);/* free skb by driver */ - precvframe->pkt = NULL; - } - - pfree_recv_queue = &precvpriv->free_recv_queue; - spin_lock_bh(&pfree_recv_queue->lock); - - list_del_init(&precvframe->list); - - list_add_tail(&precvframe->list, get_list_head(pfree_recv_queue)); - - if (padapter) { - if (pfree_recv_queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt++; - } - - spin_unlock_bh(&pfree_recv_queue->lock); - - - - return _SUCCESS; -} - -int rtw_enqueue_recvframe23a(struct recv_frame *precvframe, struct rtw_queue *queue) -{ - struct rtw_adapter *padapter = precvframe->adapter; - struct recv_priv *precvpriv = &padapter->recvpriv; - - spin_lock_bh(&queue->lock); - - list_del_init(&precvframe->list); - - list_add_tail(&precvframe->list, get_list_head(queue)); - - if (padapter) { - if (queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt++; - } - - spin_unlock_bh(&queue->lock); - - return _SUCCESS; -} - -/* -caller : defrag ; recvframe_chk_defrag23a in recv_thread (passive) -pframequeue: defrag_queue : will be accessed in recv_thread (passive) - -using spinlock to protect - -*/ - -static void rtw_free_recvframe23a_queue(struct rtw_queue *pframequeue) -{ - struct recv_frame *hdr, *ptmp; - struct list_head *phead; - - spin_lock(&pframequeue->lock); - phead = get_list_head(pframequeue); - list_for_each_entry_safe(hdr, ptmp, phead, list) - rtw_free_recvframe23a(hdr); - spin_unlock(&pframequeue->lock); -} - -u32 rtw_free_uc_swdec_pending_queue23a(struct rtw_adapter *adapter) -{ - u32 cnt = 0; - struct recv_frame *pending_frame; - - while ((pending_frame = rtw_alloc_recvframe23a(&adapter->recvpriv.uc_swdec_pending_queue))) { - rtw_free_recvframe23a(pending_frame); - DBG_8723A("%s: dequeue uc_swdec_pending_queue\n", __func__); - cnt++; - } - - return cnt; -} - -struct recv_buf *rtw_dequeue_recvbuf23a (struct rtw_queue *queue) -{ - unsigned long irqL; - struct recv_buf *precvbuf; - - spin_lock_irqsave(&queue->lock, irqL); - - precvbuf = list_first_entry_or_null(&queue->queue, - struct recv_buf, list); - if (precvbuf) - list_del_init(&precvbuf->list); - - spin_unlock_irqrestore(&queue->lock, irqL); - - return precvbuf; -} - -int recvframe_chkmic(struct rtw_adapter *adapter, - struct recv_frame *precvframe); -int recvframe_chkmic(struct rtw_adapter *adapter, - struct recv_frame *precvframe) { - - int i, res = _SUCCESS; - u32 datalen; - u8 miccode[8]; - u8 bmic_err = false, brpt_micerror = true; - u8 *pframe, *payload, *pframemic; - u8 *mickey; - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &adapter->securitypriv; - - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - - stainfo = rtw_get_stainfo23a(&adapter->stapriv, &prxattrib->ta[0]); - - if (prxattrib->encrypt == WLAN_CIPHER_SUITE_TKIP) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "recvframe_chkmic:prxattrib->encrypt == WLAN_CIPHER_SUITE_TKIP\n"); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "recvframe_chkmic:da = %pM\n", prxattrib->ra); - - /* calculate mic code */ - if (stainfo != NULL) { - if (is_multicast_ether_addr(prxattrib->ra)) { - mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0]; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "recvframe_chkmic: bcmc key\n"); - - if (!psecuritypriv->binstallGrpkey) { - res = _FAIL; - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - "recvframe_chkmic:didn't install group key!\n"); - DBG_8723A("\n recvframe_chkmic:didn't " - "install group key!!!!!!\n"); - goto exit; - } - } else { - mickey = &stainfo->dot11tkiprxmickey.skey[0]; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvframe_chkmic: unicast key\n"); - } - - /* icv_len included the mic code */ - datalen = precvframe->pkt->len-prxattrib-> - hdrlen-prxattrib->iv_len-prxattrib->icv_len - 8; - pframe = precvframe->pkt->data; - payload = pframe + prxattrib->hdrlen + - prxattrib->iv_len; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "prxattrib->iv_len =%d prxattrib->icv_len =%d\n", - prxattrib->iv_len, prxattrib->icv_len); - - /* care the length of the data */ - rtw_seccalctkipmic23a(mickey, pframe, payload, - datalen, &miccode[0], - (unsigned char)prxattrib->priority); - - pframemic = payload + datalen; - - bmic_err = false; - - for (i = 0; i < 8; i++) { - if (miccode[i] != *(pframemic + i)) { - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - "recvframe_chkmic:miccode[%d](%02x) != *(pframemic+%d)(%02x)\n", - i, miccode[i], - i, *(pframemic + i)); - bmic_err = true; - } - } - - if (bmic_err == true) { - int i; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "*(pframemic-8)-*(pframemic-1) =%*phC\n", - 8, pframemic - 8); - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "*(pframemic-16)-*(pframemic-9) =%*phC\n", - 8, pframemic - 16); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "====== demp packet (len =%d) ======\n", - precvframe->pkt->len); - for (i = 0; i < precvframe->pkt->len; i = i + 8) { - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, "%*phC\n", - 8, precvframe->pkt->data + i); - } - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "====== demp packet end [len =%d]======\n", - precvframe->pkt->len); - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "hrdlen =%d\n", prxattrib->hdrlen); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "ra = %pM psecuritypriv->binstallGrpkey =%d\n", - prxattrib->ra, - psecuritypriv->binstallGrpkey); - - /* double check key_index for some timing - issue, cannot compare with - psecuritypriv->dot118021XGrpKeyid also - cause timing issue */ - if ((is_multicast_ether_addr(prxattrib->ra)) && - (prxattrib->key_index != - pmlmeinfo->key_index)) - brpt_micerror = false; - - if ((prxattrib->bdecrypted == true) && - (brpt_micerror == true)) { - rtw_handle_tkip_mic_err23a(adapter, (u8)is_multicast_ether_addr(prxattrib->ra)); - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "mic error :prxattrib->bdecrypted =%d\n", - prxattrib->bdecrypted); - DBG_8723A(" mic error :prxattrib->" - "bdecrypted =%d\n", - prxattrib->bdecrypted); - } else { - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - "mic error :prxattrib->bdecrypted =%d\n", - prxattrib->bdecrypted); - DBG_8723A(" mic error :prxattrib->" - "bdecrypted =%d\n", - prxattrib->bdecrypted); - } - - res = _FAIL; - } else { - /* mic checked ok */ - if (!psecuritypriv->bcheck_grpkey && - is_multicast_ether_addr(prxattrib->ra)) { - psecuritypriv->bcheck_grpkey = 1; - RT_TRACE(_module_rtl871x_recv_c_, - _drv_err_, - "psecuritypriv->bcheck_grpkey = true\n"); - } - } - } else { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvframe_chkmic: rtw_get_stainfo23a ==NULL!!!\n"); - } - - skb_trim(precvframe->pkt, precvframe->pkt->len - 8); - } - -exit: - - - - return res; -} - -/* decrypt and set the ivlen, icvlen of the recv_frame */ -struct recv_frame *decryptor(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); -struct recv_frame *decryptor(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct rx_pkt_attrib *prxattrib = &precv_frame->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct recv_frame *return_packet = precv_frame; - int res = _SUCCESS; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "prxstat->decrypted =%x prxattrib->encrypt = 0x%03x\n", - prxattrib->bdecrypted, prxattrib->encrypt); - - if (prxattrib->encrypt > 0) { - u8 *iv = precv_frame->pkt->data + prxattrib->hdrlen; - - prxattrib->key_index = (((iv[3]) >> 6) & 0x3); - - if (prxattrib->key_index > WEP_KEYS) { - DBG_8723A("prxattrib->key_index(%d) > WEP_KEYS\n", - prxattrib->key_index); - - switch (prxattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - prxattrib->key_index = - psecuritypriv->dot11PrivacyKeyIndex; - break; - case WLAN_CIPHER_SUITE_TKIP: - case WLAN_CIPHER_SUITE_CCMP: - default: - prxattrib->key_index = - psecuritypriv->dot118021XGrpKeyid; - break; - } - } - } - - if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0))) { - psecuritypriv->hw_decrypted = 0; - switch (prxattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - rtw_wep_decrypt23a(padapter, precv_frame); - break; - case WLAN_CIPHER_SUITE_TKIP: - res = rtw_tkip_decrypt23a(padapter, precv_frame); - break; - case WLAN_CIPHER_SUITE_CCMP: - res = rtw_aes_decrypt23a(padapter, precv_frame); - break; - default: - break; - } - } else if (prxattrib->bdecrypted == 1 && prxattrib->encrypt > 0 && - (psecuritypriv->busetkipkey == 1 || - prxattrib->encrypt != WLAN_CIPHER_SUITE_TKIP)) { - psecuritypriv->hw_decrypted = 1; - } - - if (res == _FAIL) { - rtw_free_recvframe23a(return_packet); - return_packet = NULL; - } - - - - return return_packet; -} - -/* set the security information in the recv_frame */ -static struct recv_frame *portctrl(struct rtw_adapter *adapter, - struct recv_frame *precv_frame) -{ - u8 *psta_addr, *ptr; - uint auth_alg; - struct recv_frame *pfhdr; - struct sta_info *psta; - struct sta_priv *pstapriv ; - struct recv_frame *prtnframe; - u16 ether_type; - u16 eapol_type = ETH_P_PAE;/* for Funia BD's WPA issue */ - struct rx_pkt_attrib *pattrib; - - pstapriv = &adapter->stapriv; - - auth_alg = adapter->securitypriv.dot11AuthAlgrthm; - - pfhdr = precv_frame; - pattrib = &pfhdr->attrib; - psta_addr = pattrib->ta; - psta = rtw_get_stainfo23a(pstapriv, psta_addr); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "########portctrl:adapter->securitypriv.dot11AuthAlgrthm =%d\n", - adapter->securitypriv.dot11AuthAlgrthm); - - prtnframe = precv_frame; - - if (auth_alg == dot11AuthAlgrthm_8021X) { - /* get ether_type */ - ptr = pfhdr->pkt->data + pfhdr->attrib.hdrlen; - - ether_type = (ptr[6] << 8) | ptr[7]; - - if (psta && psta->ieee8021x_blocked) { - /* blocked */ - /* only accept EAPOL frame */ - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "########portctrl:psta->ieee8021x_blocked ==1\n"); - - if (ether_type != eapol_type) { - /* free this frame */ - rtw_free_recvframe23a(precv_frame); - prtnframe = NULL; - } - } - } - - return prtnframe; -} - -int recv_decache(struct recv_frame *precv_frame, u8 bretry, - struct stainfo_rxcache *prxcache); -int recv_decache(struct recv_frame *precv_frame, u8 bretry, - struct stainfo_rxcache *prxcache) -{ - int tid = precv_frame->attrib.priority; - - u16 seq_ctrl = ((precv_frame->attrib.seq_num & 0xffff) << 4) | - (precv_frame->attrib.frag_num & 0xf); - - - - if (tid > 15) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "recv_decache, (tid>15)! seq_ctrl = 0x%x, tid = 0x%x\n", - seq_ctrl, tid); - - return _FAIL; - } - - if (1) { /* if (bretry) */ - if (seq_ctrl == prxcache->tid_rxseq[tid]) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "recv_decache, seq_ctrl = 0x%x, tid = 0x%x, tid_rxseq = 0x%x\n", - seq_ctrl, tid, prxcache->tid_rxseq[tid]); - - return _FAIL; - } - } - - prxcache->tid_rxseq[tid] = seq_ctrl; - - - - return _SUCCESS; -} - -void process23a_pwrbit_data(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); -void process23a_pwrbit_data(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ -#ifdef CONFIG_8723AU_AP_MODE - unsigned char pwrbit; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - - psta = rtw_get_stainfo23a(pstapriv, pattrib->src); - - if (psta) { - pwrbit = ieee80211_has_pm(hdr->frame_control); - - if (pwrbit) { - if (!(psta->state & WIFI_SLEEP_STATE)) - stop_sta_xmit23a(padapter, psta); - } else { - if (psta->state & WIFI_SLEEP_STATE) - wakeup_sta_to_xmit23a(padapter, psta); - } - } - -#endif -} - -void process_wmmps_data(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); -void process_wmmps_data(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ -#ifdef CONFIG_8723AU_AP_MODE - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - - psta = rtw_get_stainfo23a(pstapriv, pattrib->src); - - if (!psta) - return; - - - if (!psta->qos_option) - return; - - if (!(psta->qos_info & 0xf)) - return; - - if (psta->state & WIFI_SLEEP_STATE) { - u8 wmmps_ac = 0; - - switch (pattrib->priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(1); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(1); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(1); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(1); - break; - } - - if (wmmps_ac) { - if (psta->sleepq_ac_len > 0) { - /* process received triggered frame */ - xmit_delivery_enabled_frames23a(padapter, psta); - } else { - /* issue one qos null frame with More data bit = 0 and the EOSP bit set (= 1) */ - issue_qos_nulldata23a(padapter, psta->hwaddr, - (u16)pattrib->priority, - 0, 0); - } - } - } - -#endif -} - -static void count_rx_stats(struct rtw_adapter *padapter, - struct recv_frame *prframe, struct sta_info *sta) -{ - int sz; - struct sta_info *psta = NULL; - struct stainfo_stats *pstats = NULL; - struct rx_pkt_attrib *pattrib = & prframe->attrib; - struct recv_priv *precvpriv = &padapter->recvpriv; - - sz = prframe->pkt->len; - precvpriv->rx_bytes += sz; - - padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++; - - if ((!is_broadcast_ether_addr(pattrib->dst)) && - (!is_multicast_ether_addr(pattrib->dst))) - padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++; - - if (sta) - psta = sta; - else - psta = prframe->psta; - - if (psta) { - pstats = &psta->sta_stats; - - pstats->rx_data_pkts++; - pstats->rx_bytes += sz; - } -} - -static int sta2sta_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info**psta) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - int ret = _SUCCESS; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u8 *mybssid = get_bssid(pmlmepriv); - u8 *myhwaddr = myid(&adapter->eeprompriv); - u8 *sta_addr = NULL; - int bmcast = is_multicast_ether_addr(pattrib->dst); - - - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - - /* filter packets that SA is myself or multicast or broadcast */ - if (ether_addr_equal(myhwaddr, pattrib->src)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "SA == myself\n"); - ret = _FAIL; - goto exit; - } - - if (!ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) { - ret = _FAIL; - goto exit; - } - - if (ether_addr_equal(pattrib->bssid, "\x0\x0\x0\x0\x0\x0") || - ether_addr_equal(mybssid, "\x0\x0\x0\x0\x0\x0") || - !ether_addr_equal(pattrib->bssid, mybssid)) { - ret = _FAIL; - goto exit; - } - - sta_addr = pattrib->src; - } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - /* For Station mode, sa and bssid should always be BSSID, - and DA is my mac-address */ - if (!ether_addr_equal(pattrib->bssid, pattrib->src)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "bssid != TA under STATION_MODE; drop pkt\n"); - ret = _FAIL; - goto exit; - } - - sta_addr = pattrib->bssid; - - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - if (bmcast) { - /* For AP mode, if DA == MCAST, then BSSID should be also MCAST */ - if (!is_multicast_ether_addr(pattrib->bssid)) { - ret = _FAIL; - goto exit; - } - } else { /* not mc-frame */ - /* For AP mode, if DA is non-MCAST, then it must - be BSSID, and bssid == BSSID */ - if (!ether_addr_equal(pattrib->bssid, pattrib->dst)) { - ret = _FAIL; - goto exit; - } - - sta_addr = pattrib->src; - } - } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - ether_addr_copy(pattrib->dst, hdr->addr1); - ether_addr_copy(pattrib->src, hdr->addr2); - ether_addr_copy(pattrib->bssid, hdr->addr3); - ether_addr_copy(pattrib->ra, pattrib->dst); - ether_addr_copy(pattrib->ta, pattrib->src); - - sta_addr = mybssid; - } else { - ret = _FAIL; - } - - if (bmcast) - *psta = rtw_get_bcmc_stainfo23a(adapter); - else - *psta = rtw_get_stainfo23a(pstapriv, sta_addr); /* get ap_info */ - - if (*psta == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "can't get psta under sta2sta_data_frame ; drop pkt\n"); - ret = _FAIL; - goto exit; - } - -exit: - - return ret; -} - -int ap2sta_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta); -int ap2sta_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - int ret = _SUCCESS; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u8 *mybssid = get_bssid(pmlmepriv); - u8 *myhwaddr = myid(&adapter->eeprompriv); - int bmcast = is_multicast_ether_addr(pattrib->dst); - - - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && - (check_fwstate(pmlmepriv, _FW_LINKED) || - check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) { - - /* filter packets that SA is myself or multicast or broadcast */ - if (ether_addr_equal(myhwaddr, pattrib->src)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "SA == myself\n"); - ret = _FAIL; - goto exit; - } - - /* da should be for me */ - if (!ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "ap2sta_data_frame: compare DA failed; DA=%pM\n", - pattrib->dst); - ret = _FAIL; - goto exit; - } - - /* check BSSID */ - if (ether_addr_equal(pattrib->bssid, "\x0\x0\x0\x0\x0\x0") || - ether_addr_equal(mybssid, "\x0\x0\x0\x0\x0\x0") || - !ether_addr_equal(pattrib->bssid, mybssid)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "ap2sta_data_frame: compare BSSID failed; BSSID=%pM\n", - pattrib->bssid); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "mybssid=%pM\n", mybssid); - - if (!bmcast) { - DBG_8723A("issue_deauth23a to the nonassociated ap=%pM for the reason(7)\n", - pattrib->bssid); - issue_deauth23a(adapter, pattrib->bssid, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - } - - ret = _FAIL; - goto exit; - } - - if (bmcast) - *psta = rtw_get_bcmc_stainfo23a(adapter); - else - /* get ap_info */ - *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid); - - if (*psta == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "ap2sta: can't get psta under STATION_MODE; drop pkt\n"); - ret = _FAIL; - goto exit; - } - - if (ieee80211_is_nullfunc(hdr->frame_control)) { - /* No data, will not indicate to upper layer, - temporily count it here */ - count_rx_stats(adapter, precv_frame, *psta); - ret = RTW_RX_HANDLED; - goto exit; - } - - } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && - check_fwstate(pmlmepriv, _FW_LINKED)) { - ether_addr_copy(pattrib->dst, hdr->addr1); - ether_addr_copy(pattrib->src, hdr->addr2); - ether_addr_copy(pattrib->bssid, hdr->addr3); - ether_addr_copy(pattrib->ra, pattrib->dst); - ether_addr_copy(pattrib->ta, pattrib->src); - - /* */ - ether_addr_copy(pattrib->bssid, mybssid); - - /* get sta_info */ - *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid); - if (*psta == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "can't get psta under MP_MODE ; drop pkt\n"); - ret = _FAIL; - goto exit; - } - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* Special case */ - ret = RTW_RX_HANDLED; - goto exit; - } else { - if (ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) { - *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid); - if (*psta == NULL) { - DBG_8723A("issue_deauth23a to the ap=%pM for the reason(7)\n", - pattrib->bssid); - - issue_deauth23a(adapter, pattrib->bssid, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - } - } - - ret = _FAIL; - } - -exit: - - - - return ret; -} - -int sta2ap_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta); -int sta2ap_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame, - struct sta_info **psta) -{ - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - unsigned char *mybssid = get_bssid(pmlmepriv); - int ret = _SUCCESS; - - - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* For AP mode, RA = BSSID, TX = STA(SRC_ADDR), A3 = DST_ADDR */ - if (!ether_addr_equal(pattrib->bssid, mybssid)) { - ret = _FAIL; - goto exit; - } - - *psta = rtw_get_stainfo23a(pstapriv, pattrib->src); - if (*psta == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "can't get psta under AP_MODE; drop pkt\n"); - DBG_8723A("issue_deauth23a to sta=%pM for the reason(7)\n", - pattrib->src); - - issue_deauth23a(adapter, pattrib->src, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - - ret = RTW_RX_HANDLED; - goto exit; - } - - process23a_pwrbit_data(adapter, precv_frame); - - /* We only get here if it's a data frame, so no need to - * confirm data frame type first */ - if (ieee80211_is_data_qos(hdr->frame_control)) - process_wmmps_data(adapter, precv_frame); - - if (ieee80211_is_nullfunc(hdr->frame_control)) { - /* No data, will not indicate to upper layer, - temporily count it here */ - count_rx_stats(adapter, precv_frame, *psta); - ret = RTW_RX_HANDLED; - goto exit; - } - } else { - u8 *myhwaddr = myid(&adapter->eeprompriv); - - if (!ether_addr_equal(pattrib->ra, myhwaddr)) { - ret = RTW_RX_HANDLED; - goto exit; - } - DBG_8723A("issue_deauth23a to sta=%pM for the reason(7)\n", - pattrib->src); - issue_deauth23a(adapter, pattrib->src, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - ret = RTW_RX_HANDLED; - goto exit; - } - -exit: - - - - return ret; -} - -static int validate_recv_ctrl_frame(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ -#ifdef CONFIG_8723AU_AP_MODE - struct rx_pkt_attrib *pattrib = &precv_frame->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - - if (!ieee80211_is_ctl(hdr->frame_control)) - return _FAIL; - - /* receive the frames that ra(a1) is my address */ - if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv))) - return _FAIL; - - /* only handle ps-poll */ - if (ieee80211_is_pspoll(hdr->frame_control)) { - struct ieee80211_pspoll *psp = (struct ieee80211_pspoll *)hdr; - u16 aid; - u8 wmmps_ac = 0; - struct sta_info *psta = NULL; - - aid = le16_to_cpu(psp->aid) & 0x3fff; - psta = rtw_get_stainfo23a(pstapriv, hdr->addr2); - - if (!psta || psta->aid != aid) - return _FAIL; - - /* for rx pkt statistics */ - psta->sta_stats.rx_ctrl_pkts++; - - switch (pattrib->priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(0); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(0); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(0); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(0); - break; - } - - if (wmmps_ac) - return _FAIL; - - if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { - DBG_8723A("%s alive check-rx ps-poll\n", __func__); - psta->expire_to = pstapriv->expire_to; - psta->state ^= WIFI_STA_ALIVE_CHK_STATE; - } - - if ((psta->state & WIFI_SLEEP_STATE) && - (pstapriv->sta_dz_bitmap & CHKBIT(psta->aid))) { - struct list_head *xmitframe_phead; - struct xmit_frame *pxmitframe; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - - xmitframe_phead = get_list_head(&psta->sleep_q); - pxmitframe = list_first_entry_or_null(xmitframe_phead, - struct xmit_frame, - list); - if (pxmitframe) { - list_del_init(&pxmitframe->list); - - psta->sleepq_len--; - - if (psta->sleepq_len>0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - - rtl8723au_hal_xmitframe_enqueue(padapter, - pxmitframe); - - if (psta->sleepq_len == 0) { - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - update_beacon23a(padapter, WLAN_EID_TIM, - NULL, false); - } - - spin_unlock_bh(&pxmitpriv->lock); - - } else { - spin_unlock_bh(&pxmitpriv->lock); - - if (pstapriv->tim_bitmap & CHKBIT(psta->aid)) { - if (psta->sleepq_len == 0) { - DBG_8723A("no buffered packets " - "to xmit\n"); - - /* issue nulldata with More data bit = 0 to indicate we have no buffered packets */ - issue_nulldata23a(padapter, - psta->hwaddr, - 0, 0, 0); - } else { - DBG_8723A("error!psta->sleepq" - "_len =%d\n", - psta->sleepq_len); - psta->sleepq_len = 0; - } - - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - - update_beacon23a(padapter, WLAN_EID_TIM, - NULL, false); - } - } - } - } - -#endif - return _FAIL; -} - -struct recv_frame *recvframe_chk_defrag23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame); -static int validate_recv_mgnt_frame(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - struct sta_info *psta; - struct sk_buff *skb; - struct ieee80211_hdr *hdr; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "+validate_recv_mgnt_frame\n"); - - precv_frame = recvframe_chk_defrag23a(padapter, precv_frame); - if (precv_frame == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "%s: fragment packet\n", __func__); - return _SUCCESS; - } - - skb = precv_frame->pkt; - hdr = (struct ieee80211_hdr *) skb->data; - - /* for rx pkt statistics */ - psta = rtw_get_stainfo23a(&padapter->stapriv, hdr->addr2); - if (psta) { - psta->sta_stats.rx_mgnt_pkts++; - - if (ieee80211_is_beacon(hdr->frame_control)) - psta->sta_stats.rx_beacon_pkts++; - else if (ieee80211_is_probe_req(hdr->frame_control)) - psta->sta_stats.rx_probereq_pkts++; - else if (ieee80211_is_probe_resp(hdr->frame_control)) { - if (ether_addr_equal(padapter->eeprompriv.mac_addr, - hdr->addr1)) - psta->sta_stats.rx_probersp_pkts++; - else if (is_broadcast_ether_addr(hdr->addr1) || - is_multicast_ether_addr(hdr->addr1)) - psta->sta_stats.rx_probersp_bm_pkts++; - else - psta->sta_stats.rx_probersp_uo_pkts++; - } - } - - mgt_dispatcher23a(padapter, precv_frame); - - return _SUCCESS; -} - -static int validate_recv_data_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame) -{ - u8 bretry; - u8 *psa, *pda; - struct sta_info *psta = NULL; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - struct security_priv *psecuritypriv = &adapter->securitypriv; - int ret = _SUCCESS; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - - - - bretry = ieee80211_has_retry(hdr->frame_control); - pda = ieee80211_get_DA(hdr); - psa = ieee80211_get_SA(hdr); - - ether_addr_copy(pattrib->dst, pda); - ether_addr_copy(pattrib->src, psa); - - switch (hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { - case cpu_to_le16(0): - ether_addr_copy(pattrib->bssid, hdr->addr3); - ether_addr_copy(pattrib->ra, pda); - ether_addr_copy(pattrib->ta, psa); - ret = sta2sta_data_frame(adapter, precv_frame, &psta); - break; - - case cpu_to_le16(IEEE80211_FCTL_FROMDS): - ether_addr_copy(pattrib->bssid, hdr->addr2); - ether_addr_copy(pattrib->ra, pda); - ether_addr_copy(pattrib->ta, hdr->addr2); - ret = ap2sta_data_frame(adapter, precv_frame, &psta); - break; - - case cpu_to_le16(IEEE80211_FCTL_TODS): - ether_addr_copy(pattrib->bssid, hdr->addr1); - ether_addr_copy(pattrib->ra, hdr->addr1); - ether_addr_copy(pattrib->ta, psa); - ret = sta2ap_data_frame(adapter, precv_frame, &psta); - break; - - case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): - /* - * There is no BSSID in this case, but the driver has been - * using addr1 so far, so keep it for now. - */ - ether_addr_copy(pattrib->bssid, hdr->addr1); - ether_addr_copy(pattrib->ra, hdr->addr1); - ether_addr_copy(pattrib->ta, hdr->addr2); - ret = _FAIL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, "case 3\n"); - break; - } - - if ((ret == _FAIL) || (ret == RTW_RX_HANDLED)) - goto exit; - - if (!psta) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "after to_fr_ds_chk; psta == NULL\n"); - ret = _FAIL; - goto exit; - } - - precv_frame->psta = psta; - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - if (ieee80211_has_a4(hdr->frame_control)) - pattrib->hdrlen += ETH_ALEN; - - /* parsing QC field */ - if (pattrib->qos == 1) { - __le16 *qptr = (__le16 *)ieee80211_get_qos_ctl(hdr); - u16 qos_ctrl = le16_to_cpu(*qptr); - - pattrib->priority = qos_ctrl & IEEE80211_QOS_CTL_TID_MASK; - pattrib->ack_policy = (qos_ctrl >> 5) & 3; - pattrib->amsdu = - (qos_ctrl & IEEE80211_QOS_CTL_A_MSDU_PRESENT) >> 7; - pattrib->hdrlen += IEEE80211_QOS_CTL_LEN; - - if (pattrib->priority != 0 && pattrib->priority != 3) { - adapter->recvpriv.bIsAnyNonBEPkts = true; - } - } else { - pattrib->priority = 0; - pattrib->ack_policy = 0; - pattrib->amsdu = 0; - } - - if (pattrib->order) { /* HT-CTRL 11n */ - pattrib->hdrlen += 4; - } - - precv_frame->preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority]; - - /* decache, drop duplicate recv packets */ - if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) == - _FAIL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "decache : drop pkt\n"); - ret = _FAIL; - goto exit; - } - - if (pattrib->privacy) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "validate_recv_data_frame:pattrib->privacy =%x\n", - pattrib->privacy); - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "^^^^^^^^^^^is_multicast_ether_addr(pattrib->ra(0x%02x)) =%d^^^^^^^^^^^^^^^6\n", - pattrib->ra[0], - is_multicast_ether_addr(pattrib->ra)); - - GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, - is_multicast_ether_addr(pattrib->ra)); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "pattrib->encrypt =%d\n", pattrib->encrypt); - - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - pattrib->iv_len = IEEE80211_WEP_IV_LEN; - pattrib->icv_len = IEEE80211_WEP_ICV_LEN; - break; - case WLAN_CIPHER_SUITE_TKIP: - pattrib->iv_len = IEEE80211_TKIP_IV_LEN; - pattrib->icv_len = IEEE80211_TKIP_ICV_LEN; - break; - case WLAN_CIPHER_SUITE_CCMP: - pattrib->iv_len = IEEE80211_CCMP_HDR_LEN; - pattrib->icv_len = IEEE80211_CCMP_MIC_LEN; - break; - default: - pattrib->iv_len = 0; - pattrib->icv_len = 0; - break; - } - } else { - pattrib->encrypt = 0; - pattrib->iv_len = 0; - pattrib->icv_len = 0; - } - -exit: - - - - return ret; -} - -static void dump_rx_pkt(struct sk_buff *skb, u16 type, int level) -{ - int i; - u8 *ptr; - - if ((level == 1) || - ((level == 2) && (type == IEEE80211_FTYPE_MGMT)) || - ((level == 3) && (type == IEEE80211_FTYPE_DATA))) { - - ptr = skb->data; - - DBG_8723A("#############################\n"); - - for (i = 0; i < 64; i = i + 8) - DBG_8723A("%*phC:\n", 8, ptr + i); - DBG_8723A("#############################\n"); - } -} - -static int validate_recv_frame(struct rtw_adapter *adapter, - struct recv_frame *precv_frame) -{ - /* shall check frame subtype, to / from ds, da, bssid */ - - /* then call check if rx seq/frag. duplicated. */ - u8 type; - u8 subtype; - int retval = _SUCCESS; - struct rx_pkt_attrib *pattrib = & precv_frame->attrib; - struct sk_buff *skb = precv_frame->pkt; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u8 ver; - u8 bDumpRxPkt; - u16 seq_ctrl, fctl; - - fctl = le16_to_cpu(hdr->frame_control); - ver = fctl & IEEE80211_FCTL_VERS; - type = fctl & IEEE80211_FCTL_FTYPE; - subtype = fctl & IEEE80211_FCTL_STYPE; - - /* add version chk */ - if (ver != 0) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "validate_recv_data_frame fail! (ver!= 0)\n"); - retval = _FAIL; - goto exit; - } - - seq_ctrl = le16_to_cpu(hdr->seq_ctrl); - pattrib->frag_num = seq_ctrl & IEEE80211_SCTL_FRAG; - pattrib->seq_num = seq_ctrl >> 4; - - pattrib->pw_save = ieee80211_has_pm(hdr->frame_control); - pattrib->mfrag = ieee80211_has_morefrags(hdr->frame_control); - pattrib->mdata = ieee80211_has_moredata(hdr->frame_control); - pattrib->privacy = ieee80211_has_protected(hdr->frame_control); - pattrib->order = ieee80211_has_order(hdr->frame_control); - - GetHalDefVar8192CUsb(adapter, HAL_DEF_DBG_DUMP_RXPKT, &bDumpRxPkt); - - if (unlikely(bDumpRxPkt == 1)) - dump_rx_pkt(skb, type, bDumpRxPkt); - - switch (type) { - case IEEE80211_FTYPE_MGMT: - retval = validate_recv_mgnt_frame(adapter, precv_frame); - if (retval == _FAIL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "validate_recv_mgnt_frame fail\n"); - } - retval = _FAIL; /* only data frame return _SUCCESS */ - break; - case IEEE80211_FTYPE_CTL: - retval = validate_recv_ctrl_frame(adapter, precv_frame); - if (retval == _FAIL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "validate_recv_ctrl_frame fail\n"); - } - retval = _FAIL; /* only data frame return _SUCCESS */ - break; - case IEEE80211_FTYPE_DATA: - pattrib->qos = (subtype & IEEE80211_STYPE_QOS_DATA) ? 1 : 0; - retval = validate_recv_data_frame(adapter, precv_frame); - if (retval == _FAIL) { - struct recv_priv *precvpriv = &adapter->recvpriv; - - precvpriv->rx_drop++; - } - break; - default: - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "validate_recv_data_frame fail! type = 0x%x\n", type); - retval = _FAIL; - break; - } - -exit: - return retval; -} - -/* remove the wlanhdr and add the eth_hdr */ - -static int wlanhdr_to_ethhdr (struct recv_frame *precvframe) -{ - u16 eth_type, len, hdrlen; - u8 bsnaphdr; - u8 *psnap; - struct rtw_adapter *adapter = precvframe->adapter; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - struct sk_buff *skb = precvframe->pkt; - u8 *ptr; - struct rx_pkt_attrib *pattrib = &precvframe->attrib; - - - - ptr = skb->data; - hdrlen = pattrib->hdrlen; - psnap = ptr + hdrlen; - eth_type = (psnap[6] << 8) | psnap[7]; - /* convert hdr + possible LLC headers into Ethernet header */ - if ((ether_addr_equal(psnap, rfc1042_header) && - eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || - ether_addr_equal(psnap, bridge_tunnel_header)) { - /* remove RFC1042 or Bridge-Tunnel encapsulation - and replace EtherType */ - bsnaphdr = true; - hdrlen += SNAP_SIZE; - } else { - /* Leave Ethernet header part of hdr and full payload */ - bsnaphdr = false; - eth_type = (psnap[0] << 8) | psnap[1]; - } - - len = skb->len - hdrlen; - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "=== pattrib->hdrlen: %x, pattrib->iv_len:%x ===\n", - pattrib->hdrlen, pattrib->iv_len); - - pattrib->eth_type = eth_type; - if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - ptr += hdrlen; - *ptr = 0x87; - *(ptr + 1) = 0x12; - - eth_type = 0x8712; - /* append rx status for mp test packets */ - - ptr = skb_pull(skb, (hdrlen - sizeof(struct ethhdr) + 2) - 24); - memcpy(ptr, skb->head, 24); - ptr += 24; - } else { - ptr = skb_pull(skb, (hdrlen - sizeof(struct ethhdr) + - (bsnaphdr ? 2:0))); - } - - ether_addr_copy(ptr, pattrib->dst); - ether_addr_copy(ptr + ETH_ALEN, pattrib->src); - - if (!bsnaphdr) { - put_unaligned_be16(len, ptr + 12); - } - - - return _SUCCESS; -} - -/* perform defrag */ -struct recv_frame *recvframe_defrag(struct rtw_adapter *adapter, - struct rtw_queue *defrag_q); -struct recv_frame *recvframe_defrag(struct rtw_adapter *adapter, - struct rtw_queue *defrag_q) -{ - struct list_head *phead; - u8 wlanhdr_offset; - u8 curfragnum; - struct recv_frame *pnfhdr, *ptmp; - struct recv_frame *prframe, *pnextrframe; - struct rtw_queue *pfree_recv_queue; - struct sk_buff *skb; - - curfragnum = 0; - pfree_recv_queue = &adapter->recvpriv.free_recv_queue; - - phead = get_list_head(defrag_q); - prframe = list_first_entry(phead, struct recv_frame, list); - list_del_init(&prframe->list); - skb = prframe->pkt; - - if (curfragnum != prframe->attrib.frag_num) { - /* the first fragment number must be 0 */ - /* free the whole queue */ - rtw_free_recvframe23a(prframe); - rtw_free_recvframe23a_queue(defrag_q); - - return NULL; - } - - curfragnum++; - - list_for_each_entry_safe(pnfhdr, ptmp, phead, list) { - pnextrframe = (struct recv_frame *)pnfhdr; - /* check the fragment sequence (2nd ~n fragment frame) */ - - if (curfragnum != pnfhdr->attrib.frag_num) { - /* the fragment number must be increasing - (after decache) */ - /* release the defrag_q & prframe */ - rtw_free_recvframe23a(prframe); - rtw_free_recvframe23a_queue(defrag_q); - return NULL; - } - - curfragnum++; - - /* copy the 2nd~n fragment frame's payload to the - first fragment */ - /* get the 2nd~last fragment frame's payload */ - - wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len; - - skb_pull(pnfhdr->pkt, wlanhdr_offset); - - /* append to first fragment frame's tail - (if privacy frame, pull the ICV) */ - - skb_trim(skb, skb->len - prframe->attrib.icv_len); - - memcpy(skb_tail_pointer(skb), pnfhdr->pkt->data, - pnfhdr->pkt->len); - - skb_put(skb, pnfhdr->pkt->len); - - prframe->attrib.icv_len = pnfhdr->attrib.icv_len; - } - - /* free the defrag_q queue and return the prframe */ - rtw_free_recvframe23a_queue(defrag_q); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "Performance defrag!!!!!\n"); - - return prframe; -} - -/* check if need to defrag, if needed queue the frame to defrag_q */ -struct recv_frame *recvframe_chk_defrag23a(struct rtw_adapter *padapter, - struct recv_frame *precv_frame) -{ - u8 ismfrag; - u8 fragnum; - u8 *psta_addr; - struct recv_frame *pfhdr; - struct sta_info *psta; - struct sta_priv *pstapriv; - struct list_head *phead; - struct recv_frame *prtnframe = NULL; - struct rtw_queue *pfree_recv_queue, *pdefrag_q; - - - - pstapriv = &padapter->stapriv; - - pfhdr = precv_frame; - - pfree_recv_queue = &padapter->recvpriv.free_recv_queue; - - /* need to define struct of wlan header frame ctrl */ - ismfrag = pfhdr->attrib.mfrag; - fragnum = pfhdr->attrib.frag_num; - - psta_addr = pfhdr->attrib.ta; - psta = rtw_get_stainfo23a(pstapriv, psta_addr); - if (!psta) { - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *) pfhdr->pkt->data; - if (!ieee80211_is_data(hdr->frame_control)) { - psta = rtw_get_bcmc_stainfo23a(padapter); - pdefrag_q = &psta->sta_recvpriv.defrag_q; - } else - pdefrag_q = NULL; - } else - pdefrag_q = &psta->sta_recvpriv.defrag_q; - - if ((ismfrag == 0) && (fragnum == 0)) { - prtnframe = precv_frame;/* isn't a fragment frame */ - } - - if (ismfrag == 1) { - /* 0~(n-1) fragment frame */ - /* enqueue to defraf_g */ - if (pdefrag_q != NULL) { - if (fragnum == 0) { - /* the first fragment */ - if (!list_empty(&pdefrag_q->queue)) { - /* free current defrag_q */ - rtw_free_recvframe23a_queue(pdefrag_q); - } - } - - /* Then enqueue the 0~(n-1) fragment into the - defrag_q */ - - /* spin_lock(&pdefrag_q->lock); */ - phead = get_list_head(pdefrag_q); - list_add_tail(&pfhdr->list, phead); - /* spin_unlock(&pdefrag_q->lock); */ - - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "Enqueuq: ismfrag = %d, fragnum = %d\n", - ismfrag, fragnum); - - prtnframe = NULL; - - } else { - /* can't find this ta's defrag_queue, - so free this recv_frame */ - rtw_free_recvframe23a(precv_frame); - prtnframe = NULL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "Free because pdefrag_q == NULL: ismfrag = %d, fragnum = %d\n", - ismfrag, fragnum); - } - } - - if ((ismfrag == 0) && (fragnum != 0)) { - /* the last fragment frame */ - /* enqueue the last fragment */ - if (pdefrag_q != NULL) { - /* spin_lock(&pdefrag_q->lock); */ - phead = get_list_head(pdefrag_q); - list_add_tail(&pfhdr->list, phead); - /* spin_unlock(&pdefrag_q->lock); */ - - /* call recvframe_defrag to defrag */ - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "defrag: ismfrag = %d, fragnum = %d\n", - ismfrag, fragnum); - precv_frame = recvframe_defrag(padapter, pdefrag_q); - prtnframe = precv_frame; - } else { - /* can't find this ta's defrag_queue, - so free this recv_frame */ - rtw_free_recvframe23a(precv_frame); - prtnframe = NULL; - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "Free because pdefrag_q == NULL: ismfrag = %d, fragnum = %d\n", - ismfrag, fragnum); - } - - } - - if ((prtnframe != NULL) && (prtnframe->attrib.privacy)) { - /* after defrag we must check tkip mic code */ - if (recvframe_chkmic(padapter, prtnframe) == _FAIL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvframe_chkmic(padapter, prtnframe) ==_FAIL\n"); - rtw_free_recvframe23a(prtnframe); - prtnframe = NULL; - } - } - - - - return prtnframe; -} - -int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe); -int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe) -{ - struct rx_pkt_attrib *pattrib; - struct sk_buff *skb, *sub_skb; - struct sk_buff_head skb_list; - - pattrib = &prframe->attrib; - - skb = prframe->pkt; - skb_pull(skb, prframe->attrib.hdrlen); - __skb_queue_head_init(&skb_list); - - ieee80211_amsdu_to_8023s(skb, &skb_list, NULL, 0, 0, false); - - while (!skb_queue_empty(&skb_list)) { - sub_skb = __skb_dequeue(&skb_list); - - sub_skb->protocol = eth_type_trans(sub_skb, padapter->pnetdev); - sub_skb->dev = padapter->pnetdev; - - sub_skb->ip_summed = CHECKSUM_NONE; - - netif_rx(sub_skb); - } - - prframe->pkt = NULL; - rtw_free_recvframe23a(prframe); - return _SUCCESS; -} - -int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num); -int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num) -{ - u8 wsize = preorder_ctrl->wsize_b; - u16 wend = (preorder_ctrl->indicate_seq + wsize -1) & 0xFFF; - - /* Rx Reorder initialize condition. */ - if (preorder_ctrl->indicate_seq == 0xFFFF) - preorder_ctrl->indicate_seq = seq_num; - - /* Drop out the packet which SeqNum is smaller than WinStart */ - if (SN_LESS(seq_num, preorder_ctrl->indicate_seq)) - return false; - - /* */ - /* Sliding window manipulation. Conditions includes: */ - /* 1. Incoming SeqNum is equal to WinStart =>Window shift 1 */ - /* 2. Incoming SeqNum is larger than the WinEnd => Window shift N */ - /* */ - if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq)) { - preorder_ctrl->indicate_seq = - (preorder_ctrl->indicate_seq + 1) & 0xFFF; - } else if (SN_LESS(wend, seq_num)) { - /* boundary situation, when seq_num cross 0xFFF */ - if (seq_num >= (wsize - 1)) - preorder_ctrl->indicate_seq = seq_num + 1 -wsize; - else - preorder_ctrl->indicate_seq = 0xFFF - (wsize - (seq_num + 1)) + 1; - } - return true; -} - -static int enqueue_reorder_recvframe23a(struct recv_reorder_ctrl *preorder_ctrl, - struct recv_frame *prframe) -{ - struct rx_pkt_attrib *pattrib = &prframe->attrib; - struct rtw_queue *ppending_recvframe_queue; - struct list_head *phead, *plist, *ptmp; - struct recv_frame *hdr; - struct rx_pkt_attrib *pnextattrib; - - ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - phead = get_list_head(ppending_recvframe_queue); - - list_for_each_safe(plist, ptmp, phead) { - hdr = container_of(plist, struct recv_frame, list); - pnextattrib = &hdr->attrib; - - if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num)) { - continue; - } else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) { - /* Duplicate entry is found!! Do not insert current entry. */ - return false; - } else { - break; - } - - } - - list_del_init(&prframe->list); - - list_add_tail(&prframe->list, plist); - - return true; -} - -int recv_indicatepkts_in_order(struct rtw_adapter *padapter, - struct recv_reorder_ctrl *preorder_ctrl, - int bforced); -int recv_indicatepkts_in_order(struct rtw_adapter *padapter, - struct recv_reorder_ctrl *preorder_ctrl, - int bforced) -{ - struct list_head *phead, *plist; - struct recv_frame *prframe; - struct rx_pkt_attrib *pattrib; - int bPktInBuf = false; - struct recv_priv *precvpriv; - struct rtw_queue *ppending_recvframe_queue; - - precvpriv = &padapter->recvpriv; - ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - phead = get_list_head(ppending_recvframe_queue); - plist = phead->next; - - /* Handling some condition for forced indicate case. */ - if (bforced) { - if (list_empty(phead)) { - return true; - } - - prframe = container_of(plist, struct recv_frame, list); - pattrib = &prframe->attrib; - preorder_ctrl->indicate_seq = pattrib->seq_num; - } - - /* Prepare indication list and indication. */ - /* Check if there is any packet need indicate. */ - while (!list_empty(phead)) { - - prframe = container_of(plist, struct recv_frame, list); - pattrib = &prframe->attrib; - - if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "recv_indicatepkts_in_order: indicate =%d seq =%d amsdu =%d\n", - preorder_ctrl->indicate_seq, - pattrib->seq_num, pattrib->amsdu); - - plist = plist->next; - list_del_init(&prframe->list); - - if (SN_EQUAL(preorder_ctrl->indicate_seq, - pattrib->seq_num)) { - preorder_ctrl->indicate_seq = - (preorder_ctrl->indicate_seq + 1)&0xFFF; - } - - if (!pattrib->amsdu) { - if ((padapter->bDriverStopped == false) && - (padapter->bSurpriseRemoved == false)) { - rtw_recv_indicatepkt23a(padapter, prframe); - } - } else { - if (amsdu_to_msdu(padapter, prframe) != - _SUCCESS) - rtw_free_recvframe23a(prframe); - } - - /* Update local variables. */ - bPktInBuf = false; - - } else { - bPktInBuf = true; - break; - } - - } - - return bPktInBuf; -} - -int recv_indicatepkt_reorder(struct rtw_adapter *padapter, - struct recv_frame *prframe); -int recv_indicatepkt_reorder(struct rtw_adapter *padapter, - struct recv_frame *prframe) -{ - int retval = _SUCCESS; - struct rx_pkt_attrib *pattrib; - struct recv_reorder_ctrl *preorder_ctrl; - struct rtw_queue *ppending_recvframe_queue; - - pattrib = &prframe->attrib; - preorder_ctrl = prframe->preorder_ctrl; - ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - - if (!pattrib->amsdu) { - /* s1. */ - wlanhdr_to_ethhdr(prframe); - - if ((pattrib->qos!= 1) || (pattrib->eth_type == ETH_P_ARP) || - (pattrib->ack_policy != 0)) { - if ((padapter->bDriverStopped == false) && - (padapter->bSurpriseRemoved == false)) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "@@@@ recv_indicatepkt_reorder -recv_func recv_indicatepkt\n"); - - rtw_recv_indicatepkt23a(padapter, prframe); - return _SUCCESS; - } - - return _FAIL; - } - - if (preorder_ctrl->enable == false) { - /* indicate this recv_frame */ - preorder_ctrl->indicate_seq = pattrib->seq_num; - rtw_recv_indicatepkt23a(padapter, prframe); - - preorder_ctrl->indicate_seq = - (preorder_ctrl->indicate_seq + 1) % 4096; - return _SUCCESS; - } - } else { - /* temp filter -> means didn't support A-MSDUs in a A-MPDU */ - if (preorder_ctrl->enable == false) { - preorder_ctrl->indicate_seq = pattrib->seq_num; - retval = amsdu_to_msdu(padapter, prframe); - - preorder_ctrl->indicate_seq = - (preorder_ctrl->indicate_seq + 1) % 4096; - return retval; - } - } - - spin_lock_bh(&ppending_recvframe_queue->lock); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "recv_indicatepkt_reorder: indicate =%d seq =%d\n", - preorder_ctrl->indicate_seq, pattrib->seq_num); - - /* s2. check if winstart_b(indicate_seq) needs to been updated */ - if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) { - goto _err_exit; - } - - /* s3. Insert all packet into Reorder Queue to maintain its ordering. */ - if (!enqueue_reorder_recvframe23a(preorder_ctrl, prframe)) { - goto _err_exit; - } - - /* s4. */ - /* Indication process. */ - /* After Packet dropping and Sliding Window shifting as above, - we can now just indicate the packets */ - /* with the SeqNum smaller than latest WinStart and buffer - other packets. */ - /* */ - /* For Rx Reorder condition: */ - /* 1. All packets with SeqNum smaller than WinStart => Indicate */ - /* 2. All packets with SeqNum larger than or equal to WinStart => - Buffer it. */ - /* */ - - if (recv_indicatepkts_in_order(padapter, preorder_ctrl, false) == true) { - mod_timer(&preorder_ctrl->reordering_ctrl_timer, - jiffies + msecs_to_jiffies(REORDER_WAIT_TIME)); - spin_unlock_bh(&ppending_recvframe_queue->lock); - } else { - spin_unlock_bh(&ppending_recvframe_queue->lock); - del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); - } - return _SUCCESS; - -_err_exit: - - spin_unlock_bh(&ppending_recvframe_queue->lock); - return _FAIL; -} - -void rtw_reordering_ctrl_timeout_handler23a(unsigned long pcontext) -{ - struct recv_reorder_ctrl *preorder_ctrl; - struct rtw_adapter *padapter; - struct rtw_queue *ppending_recvframe_queue; - - preorder_ctrl = (struct recv_reorder_ctrl *)pcontext; - padapter = preorder_ctrl->padapter; - ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; - - if (padapter->bDriverStopped || padapter->bSurpriseRemoved) { - return; - } - - spin_lock_bh(&ppending_recvframe_queue->lock); - - if (recv_indicatepkts_in_order(padapter, preorder_ctrl, true) == true) { - mod_timer(&preorder_ctrl->reordering_ctrl_timer, - jiffies + msecs_to_jiffies(REORDER_WAIT_TIME)); - } - - spin_unlock_bh(&ppending_recvframe_queue->lock); -} - -int process_recv_indicatepkts(struct rtw_adapter *padapter, - struct recv_frame *prframe); -int process_recv_indicatepkts(struct rtw_adapter *padapter, - struct recv_frame *prframe) -{ - int retval = _SUCCESS; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - if (phtpriv->ht_option == true) { /* B/G/N Mode */ - /* including perform A-MPDU Rx Ordering Buffer Control */ - if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) { - if ((padapter->bDriverStopped == false) && - (padapter->bSurpriseRemoved == false)) { - retval = _FAIL; - return retval; - } - } - } else { /* B/G mode */ - retval = wlanhdr_to_ethhdr(prframe); - if (retval != _SUCCESS) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "wlanhdr_to_ethhdr: drop pkt\n"); - return retval; - } - - if ((padapter->bDriverStopped == false) && - (padapter->bSurpriseRemoved == false)) { - /* indicate this recv_frame */ - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "@@@@ process_recv_indicatepkts- recv_func recv_indicatepkt\n"); - rtw_recv_indicatepkt23a(padapter, prframe); - } else { - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "@@@@ process_recv_indicatepkts- recv_func free_indicatepkt\n"); - - RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, - "recv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", - padapter->bDriverStopped, - padapter->bSurpriseRemoved); - retval = _FAIL; - return retval; - } - - } - - return retval; -} - -static int recv_func_prehandle(struct rtw_adapter *padapter, - struct recv_frame *rframe) -{ - int ret; - - /* check the frame crtl field and decache */ - ret = validate_recv_frame(padapter, rframe); - if (ret != _SUCCESS) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, - "recv_func: validate_recv_frame fail! drop pkt\n"); - rtw_free_recvframe23a(rframe); - goto exit; - } - -exit: - return ret; -} - -static int recv_func_posthandle(struct rtw_adapter *padapter, - struct recv_frame *prframe) -{ - int ret = _SUCCESS; - struct recv_frame *orig_prframe = prframe; - struct recv_priv *precvpriv = &padapter->recvpriv; - - /* DATA FRAME */ - prframe = decryptor(padapter, prframe); - if (prframe == NULL) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "decryptor: drop pkt\n"); - ret = _FAIL; - goto _recv_data_drop; - } - - prframe = recvframe_chk_defrag23a(padapter, prframe); - if (!prframe) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recvframe_chk_defrag23a: drop pkt\n"); - goto _recv_data_drop; - } - - /* - * Pull off crypto headers - */ - if (prframe->attrib.iv_len > 0) { - skb_pull(prframe->pkt, prframe->attrib.iv_len); - } - - if (prframe->attrib.icv_len > 0) { - skb_trim(prframe->pkt, - prframe->pkt->len - prframe->attrib.icv_len); - } - - prframe = portctrl(padapter, prframe); - if (!prframe) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "portctrl: drop pkt\n"); - ret = _FAIL; - goto _recv_data_drop; - } - - count_rx_stats(padapter, prframe, NULL); - - ret = process_recv_indicatepkts(padapter, prframe); - if (ret != _SUCCESS) { - RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, - "recv_func: process_recv_indicatepkts fail!\n"); - rtw_free_recvframe23a(orig_prframe);/* free this recv_frame */ - goto _recv_data_drop; - } - return ret; - -_recv_data_drop: - precvpriv->rx_drop++; - return ret; -} - -int rtw_recv_entry23a(struct recv_frame *rframe) -{ - int ret, r; - struct rtw_adapter *padapter = rframe->adapter; - struct rx_pkt_attrib *prxattrib = &rframe->attrib; - struct recv_priv *recvpriv = &padapter->recvpriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - - /* check if need to handle uc_swdec_pending_queue*/ - if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && - psecuritypriv->busetkipkey) { - struct recv_frame *pending_frame; - - while ((pending_frame = rtw_alloc_recvframe23a(&padapter->recvpriv.uc_swdec_pending_queue))) { - r = recv_func_posthandle(padapter, pending_frame); - if (r == _SUCCESS) - DBG_8723A("%s: dequeue uc_swdec_pending_queue\n", __func__); - } - } - - ret = recv_func_prehandle(padapter, rframe); - - if (ret == _SUCCESS) { - /* check if need to enqueue into uc_swdec_pending_queue*/ - if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && - !is_multicast_ether_addr(prxattrib->ra) && - prxattrib->encrypt > 0 && - (prxattrib->bdecrypted == 0) && - !is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm) && - !psecuritypriv->busetkipkey) { - rtw_enqueue_recvframe23a(rframe, &padapter->recvpriv.uc_swdec_pending_queue); - DBG_8723A("%s: no key, enqueue uc_swdec_pending_queue\n", __func__); - goto exit; - } - - ret = recv_func_posthandle(padapter, rframe); - - recvpriv->rx_pkts++; - } - -exit: - return ret; -} - -void rtw_signal_stat_timer_hdl23a(unsigned long data) -{ - struct rtw_adapter *adapter = (struct rtw_adapter *)data; - struct recv_priv *recvpriv = &adapter->recvpriv; - - u32 tmp_s, tmp_q; - u8 avg_signal_strength = 0; - u8 avg_signal_qual = 0; - u32 num_signal_strength = 0; - u32 num_signal_qual = 0; - u8 _alpha = 3; /* this value is based on converging_constant = 5000 */ - /* and sampling_interval = 1000 */ - - if (recvpriv->signal_strength_data.update_req == 0) { - /* update_req is clear, means we got rx */ - avg_signal_strength = recvpriv->signal_strength_data.avg_val; - num_signal_strength = recvpriv->signal_strength_data.total_num; - /* after avg_vals are acquired, we can re-stat */ - /* the signal values */ - recvpriv->signal_strength_data.update_req = 1; - } - - if (recvpriv->signal_qual_data.update_req == 0) { - /* update_req is clear, means we got rx */ - avg_signal_qual = recvpriv->signal_qual_data.avg_val; - num_signal_qual = recvpriv->signal_qual_data.total_num; - /* after avg_vals are acquired, we can re-stat */ - /*the signal values */ - recvpriv->signal_qual_data.update_req = 1; - } - - /* update value of signal_strength, rssi, signal_qual */ - if (!check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY)) { - 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->signal_qual = tmp_q; - - DBG_8723A("%s signal_strength:%3u, signal_qual:%3u, " - "num_signal_strength:%u, num_signal_qual:%u\n", - __func__, recvpriv->signal_strength, - recvpriv->signal_qual, num_signal_strength, - num_signal_qual); - } - - rtw_set_signal_stat_timer(recvpriv); -} diff --git a/drivers/staging/rtl8723au/core/rtw_security.c b/drivers/staging/rtl8723au/core/rtw_security.c deleted file mode 100644 index 5a4cfdf1ebd4..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_security.c +++ /dev/null @@ -1,1630 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_SECURITY_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <wifi.h> -#include <osdep_intf.h> - -/* WEP related ===== */ - -#define CRC32_POLY 0x04c11db7 - -struct arc4context { - u32 x; - u32 y; - u8 state[256]; -}; - -static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32 key_len) -{ - u32 t, u; - u32 keyindex; - u32 stateindex; - u8 *state; - u32 counter; - - state = parc4ctx->state; - parc4ctx->x = 0; - parc4ctx->y = 0; - for (counter = 0; counter < 256; counter++) - state[counter] = (u8)counter; - keyindex = 0; - stateindex = 0; - for (counter = 0; counter < 256; counter++) { - t = state[counter]; - stateindex = (stateindex + key[keyindex] + t) & 0xff; - u = state[stateindex]; - state[stateindex] = (u8)t; - state[counter] = (u8)u; - if (++keyindex >= key_len) - keyindex = 0; - } - -} - -static u32 arcfour_byte(struct arc4context *parc4ctx) -{ - u32 x; - u32 y; - u32 sx, sy; - u8 *state; - - state = parc4ctx->state; - x = (parc4ctx->x + 1) & 0xff; - sx = state[x]; - y = (sx + parc4ctx->y) & 0xff; - sy = state[y]; - parc4ctx->x = x; - parc4ctx->y = y; - state[y] = (u8)sx; - state[x] = (u8)sy; - - return state[(sx + sy) & 0xff]; -} - -static void arcfour_encrypt(struct arc4context *parc4ctx, u8 *dest, - u8 *src, u32 len) -{ - u32 i; - - for (i = 0; i < len; i++) - dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx); -} - -static int bcrc32initialized; -static u32 crc32_table[256]; - -static u8 crc32_reverseBit(u8 data) -{ - u8 retval = ((data << 7) & 0x80) | ((data << 5) & 0x40) | - ((data << 3) & 0x20) | ((data << 1) & 0x10) | - ((data >> 1) & 0x08) | ((data >> 3) & 0x04) | - ((data >> 5) & 0x02) | ((data >> 7) & 0x01); - return retval; -} - -static void crc32_init(void) -{ - int i, j; - u32 c; - u8 *p, *p1; - u8 k; - - if (bcrc32initialized == 1) - return; - - p = (u8 *) &c; - c = 0x12340000; - - for (i = 0; i < 256; ++i) { - k = crc32_reverseBit((u8)i); - - for (c = ((u32)k) << 24, j = 8; j > 0; --j) - c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1); - - p1 = (u8 *)&crc32_table[i]; - - p1[0] = crc32_reverseBit(p[3]); - p1[1] = crc32_reverseBit(p[2]); - p1[2] = crc32_reverseBit(p[1]); - p1[3] = crc32_reverseBit(p[0]); - } - - bcrc32initialized = 1; -} - -static u32 getcrc32(u8 *buf, int len) -{ - u8 *p; - u32 crc; - - if (bcrc32initialized == 0) - crc32_init(); - - crc = 0xffffffff; /* preload shift register, per CRC-32 spec */ - - for (p = buf; len > 0; ++p, --len) - crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8); - - return ~crc; /* transmit complement, per CRC-32 spec */ -} - -/* Need to consider the fragment situation */ -void rtw_wep_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - /* exclude ICV */ - __le32 crc; - struct arc4context mycontext; - int curfragnum, length, index; - u32 keylength; - u8 *pframe, *payload, *iv; /* wepkey */ - u8 wepkey[16]; - u8 hw_hdr_offset = 0; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (!pxmitframe->buf_addr) - return; - - hw_hdr_offset = TXDESC_OFFSET; - - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - /* start to encrypt each fragment */ - if (pattrib->encrypt != WLAN_CIPHER_SUITE_WEP40 && - pattrib->encrypt != WLAN_CIPHER_SUITE_WEP104) - return; - - index = psecuritypriv->dot11PrivacyKeyIndex; - keylength = psecuritypriv->wep_key[index].keylen; - - for (curfragnum = 0; curfragnum < pattrib->nr_frags ; curfragnum++) { - iv = pframe + pattrib->hdrlen; - memcpy(&wepkey[0], iv, 3); - memcpy(&wepkey[3], &psecuritypriv->wep_key[index].key, - keylength); - payload = pframe + pattrib->iv_len + pattrib->hdrlen; - - if ((curfragnum + 1) == pattrib->nr_frags) { - /* the last fragment */ - length = pattrib->last_txcmdsz - pattrib->hdrlen - - pattrib->iv_len - pattrib->icv_len; - - crc = cpu_to_le32(getcrc32(payload, length)); - - arcfour_init(&mycontext, wepkey, 3 + keylength); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload + length, - (char *)&crc, 4); - } else { - length = pxmitpriv->frag_len - pattrib->hdrlen - - pattrib->iv_len - pattrib->icv_len; - crc = cpu_to_le32(getcrc32(payload, length)); - arcfour_init(&mycontext, wepkey, 3 + keylength); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload + length, - (char *)&crc, 4); - - pframe += pxmitpriv->frag_len; - pframe = PTR_ALIGN(pframe, 4); - } - } - -} - -void rtw_wep_decrypt23a(struct rtw_adapter *padapter, - struct recv_frame *precvframe) -{ - /* exclude ICV */ - u32 actual_crc, expected_crc; - struct arc4context mycontext; - int length; - u32 keylength; - u8 *pframe, *payload, *iv, wepkey[16]; - u8 keyindex; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sk_buff *skb = precvframe->pkt; - - pframe = skb->data; - - /* start to decrypt recvframe */ - if (prxattrib->encrypt != WLAN_CIPHER_SUITE_WEP40 && - prxattrib->encrypt != WLAN_CIPHER_SUITE_WEP104) - return; - - iv = pframe + prxattrib->hdrlen; - /* keyindex = (iv[3]&0x3); */ - keyindex = prxattrib->key_index; - keylength = psecuritypriv->wep_key[keyindex].keylen; - memcpy(&wepkey[0], iv, 3); - /* memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength); */ - memcpy(&wepkey[3], &psecuritypriv->wep_key[keyindex].key, keylength); - length = skb->len - prxattrib->hdrlen - prxattrib->iv_len; - - payload = pframe + prxattrib->iv_len + prxattrib->hdrlen; - - /* decrypt payload include icv */ - arcfour_init(&mycontext, wepkey, 3 + keylength); - arcfour_encrypt(&mycontext, payload, payload, length); - - /* calculate icv and compare the icv */ - actual_crc = getcrc32(payload, length - 4); - expected_crc = get_unaligned_le32(&payload[length - 4]); - - if (actual_crc != expected_crc) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s:icv CRC mismatch: " - "actual: %08x, expected: %08x\n", - __func__, actual_crc, expected_crc); - } -} - -/* 3 ===== TKIP related ===== */ - -static u32 secmicgetuint32(u8 *p) -/* Convert from Byte[] to u32 in a portable way */ -{ - s32 i; - u32 res = 0; - - for (i = 0; i < 4; i++) - res |= ((u32)(*p++)) << (8 * i); - - return res; -} - -static void secmicputuint32(u8 *p, u32 val) -/* Convert from long to Byte[] in a portable way */ -{ - long i; - - for (i = 0; i < 4; i++) { - *p++ = (u8) (val & 0xff); - val >>= 8; - } - -} - -static void secmicclear(struct mic_data *pmicdata) -{ -/* Reset the state to the empty message. */ - - pmicdata->L = pmicdata->K0; - pmicdata->R = pmicdata->K1; - pmicdata->nBytesInM = 0; - pmicdata->M = 0; - -} - -void rtw_secmicsetkey23a(struct mic_data *pmicdata, u8 *key) -{ - /* Set the key */ - - pmicdata->K0 = secmicgetuint32(key); - pmicdata->K1 = secmicgetuint32(key + 4); - /* and reset the message */ - secmicclear(pmicdata); - -} - -void rtw_secmicappend23abyte23a(struct mic_data *pmicdata, u8 b) -{ - - /* Append the byte to our word-sized buffer */ - pmicdata->M |= ((unsigned long)b) << (8 * pmicdata->nBytesInM); - pmicdata->nBytesInM++; - /* Process the word if it is full. */ - if (pmicdata->nBytesInM >= 4) { - pmicdata->L ^= pmicdata->M; - pmicdata->R ^= ROL32(pmicdata->L, 17); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | ((pmicdata->L & 0x00ff00ff) << 8); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ROL32(pmicdata->L, 3); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ROR32(pmicdata->L, 2); - pmicdata->L += pmicdata->R; - /* Clear the buffer */ - pmicdata->M = 0; - pmicdata->nBytesInM = 0; - } - -} - -void rtw_secmicappend23a(struct mic_data *pmicdata, u8 *src, u32 nbytes) -{ - - /* This is simple */ - while (nbytes > 0) { - rtw_secmicappend23abyte23a(pmicdata, *src++); - nbytes--; - } - -} - -void rtw_secgetmic23a(struct mic_data *pmicdata, u8 *dst) -{ - - /* Append the minimum padding */ - rtw_secmicappend23abyte23a(pmicdata, 0x5a); - rtw_secmicappend23abyte23a(pmicdata, 0); - rtw_secmicappend23abyte23a(pmicdata, 0); - rtw_secmicappend23abyte23a(pmicdata, 0); - rtw_secmicappend23abyte23a(pmicdata, 0); - /* and then zeroes until the length is a multiple of 4 */ - while (pmicdata->nBytesInM != 0) - rtw_secmicappend23abyte23a(pmicdata, 0); - /* The appendByte function has already computed the result. */ - secmicputuint32(dst, pmicdata->L); - secmicputuint32(dst + 4, pmicdata->R); - /* Reset to the empty message. */ - secmicclear(pmicdata); - -} - -void rtw_seccalctkipmic23a(u8 *key, u8 *header, u8 *data, u32 data_len, - u8 *mic_code, u8 pri) -{ - - struct mic_data micdata; - u8 priority[4] = {0x0, 0x0, 0x0, 0x0}; - - rtw_secmicsetkey23a(&micdata, key); - priority[0] = pri; - - /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */ - if (header[1]&1) { /* ToDS == 1 */ - rtw_secmicappend23a(&micdata, &header[16], 6); /* DA */ - if (header[1]&2) /* From Ds == 1 */ - rtw_secmicappend23a(&micdata, &header[24], 6); - else - rtw_secmicappend23a(&micdata, &header[10], 6); - } else { /* ToDS == 0 */ - rtw_secmicappend23a(&micdata, &header[4], 6); /* DA */ - if (header[1]&2) /* From Ds == 1 */ - rtw_secmicappend23a(&micdata, &header[16], 6); - else - rtw_secmicappend23a(&micdata, &header[10], 6); - - } - rtw_secmicappend23a(&micdata, &priority[0], 4); - - rtw_secmicappend23a(&micdata, data, data_len); - - rtw_secgetmic23a(&micdata, mic_code); - -} - -/* macros for extraction/creation of unsigned char/unsigned short values */ -#define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15)) -#define Lo8(v16) ((u8)((v16) & 0x00FF)) -#define Hi8(v16) ((u8)(((v16) >> 8) & 0x00FF)) -#define Lo16(v32) ((u16)((v32) & 0xFFFF)) -#define Hi16(v32) ((u16)(((v32) >> 16) & 0xFFFF)) -#define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8)) - -/* select the Nth 16-bit word of the temporal key unsigned char array TK[] */ -#define TK16(N) Mk16(tk[2 * (N) + 1], tk[2 * (N)]) - -/* S-box lookup: 16 bits --> 16 bits */ -#define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)]) - -/* fixed algorithm "parameters" */ -#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */ -#define TA_SIZE 6 /* 48-bit transmitter address */ -#define TK_SIZE 16 /* 128-bit temporal key */ -#define P1K_SIZE 10 /* 80-bit Phase1 key */ -#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */ - -/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */ -static const unsigned short Sbox1[2][256] = { - /* Sbox for hash (can be in ROM) */ - { - 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, - 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, - 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, - 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, - 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, - 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, - 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, - 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, - 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, - 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, - 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, - 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, - 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, - 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, - 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, - 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, - 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, - 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, - 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, - 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, - 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, - 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, - 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, - 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, - 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, - 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, - 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, - 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, - 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, - 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, - 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, - 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, - }, - { /* second half of table is unsigned char-reversed version of first! */ - 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491, - 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC, - 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB, - 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B, - 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83, - 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A, - 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F, - 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA, - 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B, - 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713, - 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6, - 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85, - 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411, - 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B, - 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1, - 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF, - 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E, - 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6, - 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B, - 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD, - 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8, - 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2, - 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049, - 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810, - 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197, - 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F, - 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C, - 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927, - 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733, - 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5, - 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0, - 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C, - } -}; - - /* -********************************************************************** -* Routine: Phase 1 -- generate P1K, given TA, TK, IV32 -* -* Inputs: -* tk[] = temporal key [128 bits] -* ta[] = transmitter's MAC address [ 48 bits] -* iv32 = upper 32 bits of IV [ 32 bits] -* Output: -* p1k[] = Phase 1 key [ 80 bits] -* -* Note: -* This function only needs to be called every 2**16 packets, -* although in theory it could be called every packet. -* -********************************************************************** -*/ -static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32) -{ - int i; - - /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */ - p1k[0] = Lo16(iv32); - p1k[1] = Hi16(iv32); - p1k[2] = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */ - p1k[3] = Mk16(ta[3], ta[2]); - p1k[4] = Mk16(ta[5], ta[4]); - - /* Now compute an unbalanced Feistel cipher with 80-bit block */ - /* size on the 80-bit block P1K[], using the 128-bit key TK[] */ - for (i = 0; i < PHASE1_LOOP_CNT; i++) { - /* Each add operation here is mod 2**16 */ - p1k[0] += _S_(p1k[4] ^ TK16((i & 1) + 0)); - p1k[1] += _S_(p1k[0] ^ TK16((i & 1) + 2)); - p1k[2] += _S_(p1k[1] ^ TK16((i & 1) + 4)); - p1k[3] += _S_(p1k[2] ^ TK16((i & 1) + 6)); - p1k[4] += _S_(p1k[3] ^ TK16((i & 1) + 0)); - p1k[4] += (unsigned short) i; /* avoid "slide attacks" */ - } - -} - -/* -********************************************************************** -* Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16 -* -* Inputs: -* tk[] = Temporal key [128 bits] -* p1k[] = Phase 1 output key [ 80 bits] -* iv16 = low 16 bits of IV counter [ 16 bits] -* Output: -* rc4key[] = the key used to encrypt the packet [128 bits] -* -* Note: -* The value {TA, IV32, IV16} for Phase1/Phase2 must be unique -* across all packets using the same key TK value. Then, for a -* given value of TK[], this TKIP48 construction guarantees that -* the final RC4KEY value is unique across all packets. -* -* Suggested implementation optimization: if PPK[] is "overlaid" -* appropriately on RC4KEY[], there is no need for the final -* for loop below that copies the PPK[] result into RC4KEY[]. -* -********************************************************************** -*/ -static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16) -{ - int i; - u16 PPK[6]; /* temporary key for mixing */ - - /* Note: all adds in the PPK[] equations below are mod 2**16 */ - for (i = 0; i < 5; i++) - PPK[i] = p1k[i]; /* first, copy P1K to PPK */ - - PPK[5] = p1k[4] + iv16; /* next, add in IV16 */ - - /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */ - PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */ - PPK[1] += _S_(PPK[0] ^ TK16(1)); - PPK[2] += _S_(PPK[1] ^ TK16(2)); - PPK[3] += _S_(PPK[2] ^ TK16(3)); - PPK[4] += _S_(PPK[3] ^ TK16(4)); - PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */ - - /* Final sweep: bijective, "linear". Rotates kill LSB correlations */ - PPK[0] += RotR1(PPK[5] ^ TK16(6)); - PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */ - PPK[2] += RotR1(PPK[1]); - PPK[3] += RotR1(PPK[2]); - PPK[4] += RotR1(PPK[3]); - PPK[5] += RotR1(PPK[4]); - /* Note: At this point, for a given key TK[0..15], the 96-bit output */ - /* value PPK[0..5] is guaranteed to be unique, as a function */ - /* of the 96-bit "input" value {TA, IV32, IV16}. That is, */ - /* P1K is now a keyed permutation of {TA, IV32, IV16}. */ - - /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */ - rc4key[0] = Hi8(iv16); /* RC4KEY[0..2] is the WEP IV */ - rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */ - rc4key[2] = Lo8(iv16); - rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1); - - /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */ - for (i = 0; i < 6; i++) { - rc4key[4 + 2 * i] = Lo8(PPK[i]); - rc4key[5 + 2 * i] = Hi8(PPK[i]); - } - -} - -/* The hlen isn't include the IV */ -int rtw_tkip_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - u16 pnl; - u32 pnh; - u8 rc4key[16]; - u8 ttkey[16]; - __le32 crc; - u8 hw_hdr_offset = 0; - struct arc4context mycontext; - int curfragnum, length; - u8 *pframe, *payload, *iv, *prwskey; - union pn48 dot11txpn; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int res = _SUCCESS; - - if (pattrib->encrypt != WLAN_CIPHER_SUITE_TKIP) - return _FAIL; - - if (!pxmitframe->buf_addr) - return _FAIL; - - hw_hdr_offset = TXDESC_OFFSET; - - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - if (pattrib->psta) - stainfo = pattrib->psta; - else { - DBG_8723A("%s, call rtw_get_stainfo()\n", __func__); - stainfo = rtw_get_stainfo23a(&padapter->stapriv, - &pattrib->ra[0]); - } - - if (!stainfo) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo == NULL!!!\n", __func__); - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo!= NULL!!!\n", __func__); - - if (!(stainfo->state & _FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state); - return _FAIL; - } - - if (is_multicast_ether_addr(pattrib->ra)) - prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; - else - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - - /* 4 start to encrypt each fragment */ - for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - iv = pframe + pattrib->hdrlen; - payload = pframe + pattrib->iv_len + pattrib->hdrlen; - - GET_TKIP_PN(iv, dot11txpn); - - pnl = (u16)(dot11txpn.val); - pnh = (u32)(dot11txpn.val>>16); - - phase1((u16 *)&ttkey[0], prwskey, &pattrib->ta[0], pnh); - - phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl); - - if ((curfragnum + 1) == pattrib->nr_frags) { /* 4 the last fragment */ - length = (pattrib->last_txcmdsz - - pattrib->hdrlen - - pattrib->iv_len - - pattrib->icv_len); - - RT_TRACE(_module_rtl871x_security_c_, _drv_info_, - "pattrib->iv_len =%x, pattrib->icv_len =%x\n", - pattrib->iv_len, - pattrib->icv_len); - crc = cpu_to_le32(getcrc32(payload, length)); - - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload + length, - (char *)&crc, 4); - - } else { - length = (pxmitpriv->frag_len - - pattrib->hdrlen - - pattrib->iv_len - - pattrib->icv_len); - - crc = cpu_to_le32(getcrc32(payload, length)); - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, payload, length); - arcfour_encrypt(&mycontext, payload + length, - (char *)&crc, 4); - - pframe += pxmitpriv->frag_len; - pframe = PTR_ALIGN(pframe, 4); - } - } - - return res; -} - -/* The hlen isn't include the IV */ -int rtw_tkip_decrypt23a(struct rtw_adapter *padapter, - struct recv_frame *precvframe) -{ - u16 pnl; - u32 pnh; - u8 rc4key[16]; - u8 ttkey[16]; - u32 actual_crc, expected_crc; - struct arc4context mycontext; - int length; - u8 *pframe, *payload, *iv, *prwskey; - union pn48 dot11txpn; - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sk_buff *skb = precvframe->pkt; - int res = _SUCCESS; - - if (prxattrib->encrypt != WLAN_CIPHER_SUITE_TKIP) - return _FAIL; - - pframe = skb->data; - - stainfo = rtw_get_stainfo23a(&padapter->stapriv, - &prxattrib->ta[0]); - if (!stainfo) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo == NULL!!!\n", __func__); - return _FAIL; - } - - /* 4 start to decrypt recvframe */ - if (is_multicast_ether_addr(prxattrib->ra)) { - if (psecuritypriv->binstallGrpkey == 0) { - res = _FAIL; - DBG_8723A("%s:rx bc/mc packets, but didn't install group key!!!!!!!!!!\n", __func__); - goto exit; - } - prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey; - } else { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo!= NULL!!!\n", __func__); - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - } - - iv = pframe + prxattrib->hdrlen; - payload = pframe + prxattrib->iv_len + prxattrib->hdrlen; - length = skb->len - prxattrib->hdrlen - prxattrib->iv_len; - - GET_TKIP_PN(iv, dot11txpn); - - pnl = (u16)(dot11txpn.val); - pnh = (u32)(dot11txpn.val>>16); - - phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh); - phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl); - - /* 4 decrypt payload include icv */ - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, payload, length); - - actual_crc = getcrc32(payload, length - 4); - expected_crc = get_unaligned_le32(&payload[length - 4]); - - if (actual_crc != expected_crc) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s:icv CRC mismatch: " - "actual: %08x, expected: %08x\n", - __func__, actual_crc, expected_crc); - res = _FAIL; - } - -exit: - return res; -} - -/* 3 ===== AES related ===== */ - -#define MAX_MSG_SIZE 2048 -/*****************************/ -/******** SBOX Table *********/ -/*****************************/ - -static u8 sbox_table[256] = { - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, - 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, - 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, - 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, - 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, - 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, - 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, - 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, - 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, - 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, - 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, - 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 -}; - -/*****************************/ -/**** Function Prototypes ****/ -/*****************************/ - -static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, - int qc_exists); - -static void xor_128(u8 *a, u8 *b, u8 *out) -{ - int i; - - for (i = 0; i < 16; i++) - out[i] = a[i] ^ b[i]; -} - -static void xor_32(u8 *a, u8 *b, u8 *out) -{ - int i; - - for (i = 0; i < 4; i++) - out[i] = a[i] ^ b[i]; -} - -static u8 sbox(u8 a) -{ - return sbox_table[(int)a]; -} - -static void next_key(u8 *key, int round) -{ - u8 rcon; - u8 sbox_key[4]; - u8 rcon_table[12] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, - 0x1b, 0x36, 0x36, 0x36 - }; - - sbox_key[0] = sbox(key[13]); - sbox_key[1] = sbox(key[14]); - sbox_key[2] = sbox(key[15]); - sbox_key[3] = sbox(key[12]); - - rcon = rcon_table[round]; - - xor_32(&key[0], sbox_key, &key[0]); - key[0] = key[0] ^ rcon; - - xor_32(&key[4], &key[0], &key[4]); - xor_32(&key[8], &key[4], &key[8]); - xor_32(&key[12], &key[8], &key[12]); - -} - -static void byte_sub(u8 *in, u8 *out) -{ - int i; - - for (i = 0; i < 16; i++) - out[i] = sbox(in[i]); -} - -static void shift_row(u8 *in, u8 *out) -{ - - out[0] = in[0]; - out[1] = in[5]; - out[2] = in[10]; - out[3] = in[15]; - out[4] = in[4]; - out[5] = in[9]; - out[6] = in[14]; - out[7] = in[3]; - out[8] = in[8]; - out[9] = in[13]; - out[10] = in[2]; - out[11] = in[7]; - out[12] = in[12]; - out[13] = in[1]; - out[14] = in[6]; - out[15] = in[11]; - -} - -static void mix_column(u8 *in, u8 *out) -{ - int i; - u8 add1b[4]; - u8 add1bf7[4]; - u8 rotl[4]; - u8 swap_halfs[4]; - u8 andf7[4]; - u8 rotr[4]; - u8 temp[4]; - u8 tempb[4]; - - for (i = 0; i < 4; i++) { - if ((in[i] & 0x80) == 0x80) - add1b[i] = 0x1b; - else - add1b[i] = 0x00; - } - - swap_halfs[0] = in[2]; /* Swap halfs */ - swap_halfs[1] = in[3]; - swap_halfs[2] = in[0]; - swap_halfs[3] = in[1]; - - rotl[0] = in[3]; /* Rotate left 8 bits */ - rotl[1] = in[0]; - rotl[2] = in[1]; - rotl[3] = in[2]; - - andf7[0] = in[0] & 0x7f; - andf7[1] = in[1] & 0x7f; - andf7[2] = in[2] & 0x7f; - andf7[3] = in[3] & 0x7f; - - for (i = 3; i > 0; i--) { /* logical shift left 1 bit */ - andf7[i] = andf7[i] << 1; - if ((andf7[i - 1] & 0x80) == 0x80) - andf7[i] = (andf7[i] | 0x01); - } - andf7[0] = andf7[0] << 1; - andf7[0] = andf7[0] & 0xfe; - - xor_32(add1b, andf7, add1bf7); - - xor_32(in, add1bf7, rotr); - - temp[0] = rotr[0]; /* Rotate right 8 bits */ - rotr[0] = rotr[1]; - rotr[1] = rotr[2]; - rotr[2] = rotr[3]; - rotr[3] = temp[0]; - - xor_32(add1bf7, rotr, temp); - xor_32(swap_halfs, rotl, tempb); - xor_32(temp, tempb, out); - -} - -static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext) -{ - int round; - int i; - u8 intermediatea[16]; - u8 intermediateb[16]; - u8 round_key[16]; - - for (i = 0; i < 16; i++) - round_key[i] = key[i]; - - for (round = 0; round < 11; round++) { - if (round == 0) { - xor_128(round_key, data, ciphertext); - next_key(round_key, round); - } else if (round == 10) { - byte_sub(ciphertext, intermediatea); - shift_row(intermediatea, intermediateb); - xor_128(intermediateb, round_key, ciphertext); - } else { /* 1 - 9 */ - byte_sub(ciphertext, intermediatea); - shift_row(intermediatea, intermediateb); - mix_column(&intermediateb[0], &intermediatea[0]); - mix_column(&intermediateb[4], &intermediatea[4]); - mix_column(&intermediateb[8], &intermediatea[8]); - mix_column(&intermediateb[12], &intermediatea[12]); - xor_128(intermediatea, round_key, ciphertext); - next_key(round_key, round); - } - } - -} - -/************************************************/ -/* construct_mic_iv() */ -/* Builds the MIC IV from header fields and PN */ -/************************************************/ -static void construct_mic_iv(u8 *mic_iv, int qc_exists, int a4_exists, u8 *mpdu, - uint payload_length, u8 *pn_vector) -{ - int i; - - mic_iv[0] = 0x59; - if (qc_exists && a4_exists) - mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ - if (qc_exists && !a4_exists) - mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ - if (!qc_exists) - mic_iv[1] = 0x00; - for (i = 2; i < 8; i++) - mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */ - for (i = 8; i < 14; i++) - mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ - mic_iv[14] = (unsigned char)(payload_length / 256); - mic_iv[15] = (unsigned char)(payload_length % 256); -} - -/************************************************/ -/* construct_mic_header1() */ -/* Builds the first MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_mic_header1(u8 *mic_header1, int header_length, u8 *mpdu) -{ - mic_header1[0] = (u8)((header_length - 2) / 256); - mic_header1[1] = (u8)((header_length - 2) % 256); - mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ - mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */ - mic_header1[4] = mpdu[4]; /* A1 */ - mic_header1[5] = mpdu[5]; - mic_header1[6] = mpdu[6]; - mic_header1[7] = mpdu[7]; - mic_header1[8] = mpdu[8]; - mic_header1[9] = mpdu[9]; - mic_header1[10] = mpdu[10]; /* A2 */ - mic_header1[11] = mpdu[11]; - mic_header1[12] = mpdu[12]; - mic_header1[13] = mpdu[13]; - mic_header1[14] = mpdu[14]; - mic_header1[15] = mpdu[15]; - -} - -/************************************************/ -/* construct_mic_header2() */ -/* Builds the last MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, - int qc_exists) -{ - int i; - - for (i = 0; i < 16; i++) - mic_header2[i] = 0x00; - - mic_header2[0] = mpdu[16]; /* A3 */ - mic_header2[1] = mpdu[17]; - mic_header2[2] = mpdu[18]; - mic_header2[3] = mpdu[19]; - mic_header2[4] = mpdu[20]; - mic_header2[5] = mpdu[21]; - - mic_header2[6] = 0x00; - mic_header2[7] = 0x00; /* mpdu[23]; */ - - if (!qc_exists && a4_exists) { - for (i = 0; i < 6; i++) - mic_header2[8+i] = mpdu[24+i]; /* A4 */ - } - - if (qc_exists && !a4_exists) { - mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */ - mic_header2[9] = mpdu[25] & 0x00; - } - - if (qc_exists && a4_exists) { - for (i = 0; i < 6; i++) - mic_header2[8+i] = mpdu[24+i]; /* A4 */ - - mic_header2[14] = mpdu[30] & 0x0f; - mic_header2[15] = mpdu[31] & 0x00; - } - -} - -/************************************************/ -/* construct_mic_header2() */ -/* Builds the last MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_ctr_preload(u8 *ctr_preload, int a4_exists, int qc_exists, - u8 *mpdu, u8 *pn_vector, int c) -{ - int i = 0; - - for (i = 0; i < 16; i++) - ctr_preload[i] = 0x00; - - i = 0; - - ctr_preload[0] = 0x01; /* flag */ - if (qc_exists && a4_exists) - ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */ - if (qc_exists && !a4_exists) - ctr_preload[1] = mpdu[24] & 0x0f; - - for (i = 2; i < 8; i++) - ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */ - for (i = 8; i < 14; i++) - ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */ - ctr_preload[14] = (unsigned char) (c / 256); /* Ctr */ - ctr_preload[15] = (unsigned char) (c % 256); - -} - -/************************************/ -/* bitwise_xor() */ -/* A 128 bit, bitwise exclusive or */ -/************************************/ -static void bitwise_xor(u8 *ina, u8 *inb, u8 *out) -{ - int i; - - for (i = 0; i < 16; i++) - out[i] = ina[i] ^ inb[i]; -} - -static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen) -{ - uint qc_exists, a4_exists, i, j, payload_remainder, - num_blocks, payload_index; - u8 pn_vector[6]; - u8 mic_iv[16]; - u8 mic_header1[16]; - u8 mic_header2[16]; - u8 ctr_preload[16]; - /* Intermediate Buffers */ - u8 chain_buffer[16]; - u8 aes_out[16]; - u8 padded_buffer[16]; - u8 mic[8]; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe; - u16 frsubtype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE; - - memset((void *)mic_iv, 0, 16); - memset((void *)mic_header1, 0, 16); - memset((void *)mic_header2, 0, 16); - memset((void *)ctr_preload, 0, 16); - memset((void *)chain_buffer, 0, 16); - memset((void *)aes_out, 0, 16); - memset((void *)padded_buffer, 0, 16); - - if ((hdrlen == sizeof(struct ieee80211_hdr_3addr) || - (hdrlen == sizeof(struct ieee80211_qos_hdr)))) - a4_exists = 0; - else - a4_exists = 1; - - if (ieee80211_is_data(hdr->frame_control)) { - if ((frsubtype == IEEE80211_STYPE_DATA_CFACK) || - (frsubtype == IEEE80211_STYPE_DATA_CFPOLL) || - (frsubtype == IEEE80211_STYPE_DATA_CFACKPOLL)) { - qc_exists = 1; - if (hdrlen != sizeof(struct ieee80211_qos_hdr)) - hdrlen += 2; - } else if ((frsubtype == IEEE80211_STYPE_QOS_DATA) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACK) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFPOLL) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACKPOLL)) { - if (hdrlen != sizeof(struct ieee80211_qos_hdr)) - hdrlen += 2; - qc_exists = 1; - } else { - qc_exists = 0; - } - } else { - qc_exists = 0; - } - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - - construct_mic_iv(mic_iv, qc_exists, a4_exists, pframe, plen, pn_vector); - - construct_mic_header1(mic_header1, hdrlen, pframe); - construct_mic_header2(mic_header2, pframe, a4_exists, qc_exists); - - payload_remainder = plen % 16; - num_blocks = plen / 16; - - /* Find start of payload */ - payload_index = hdrlen + 8; - - /* Calculate MIC */ - aes128k128d(key, mic_iv, aes_out); - bitwise_xor(aes_out, mic_header1, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - bitwise_xor(aes_out, mic_header2, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - - for (i = 0; i < num_blocks; i++) { - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); - - payload_index += 16; - aes128k128d(key, chain_buffer, aes_out); - } - - /* Add on the final payload block if it needs padding */ - if (payload_remainder > 0) { - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index++]; - bitwise_xor(aes_out, padded_buffer, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - } - - for (j = 0; j < 8; j++) - mic[j] = aes_out[j]; - - /* Insert MIC into payload */ - for (j = 0; j < 8; j++) - pframe[payload_index + j] = mic[j]; - - payload_index = hdrlen + 8; - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - pframe, pn_vector, i + 1); - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); - for (j = 0; j < 16; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - if (payload_remainder > 0) { - /* If there is a short final block, then pad it, - * encrypt it and copy the unpadded part back - */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, - pn_vector, num_blocks + 1); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - /* Encrypt the MIC */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, - pn_vector, 0); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < 8; j++) - padded_buffer[j] = pframe[j + hdrlen + 8 + plen]; - - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < 8; j++) - pframe[payload_index++] = chain_buffer[j]; - - return _SUCCESS; -} - -int rtw_aes_encrypt23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ /* exclude ICV */ - /* Intermediate Buffers */ - int curfragnum, length; - u8 *pframe, *prwskey; - u8 hw_hdr_offset = 0; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int res = _SUCCESS; - - if (!pxmitframe->buf_addr) - return _FAIL; - - hw_hdr_offset = TXDESC_OFFSET; - - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - /* 4 start to encrypt each fragment */ - if (pattrib->encrypt != WLAN_CIPHER_SUITE_CCMP) - return _FAIL; - - if (pattrib->psta) { - stainfo = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - stainfo = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - - if (!stainfo) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo == NULL!!!\n", __func__); - DBG_8723A("%s, psta == NUL\n", __func__); - res = _FAIL; - goto out; - } - if (!(stainfo->state & _FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", - __func__, stainfo->state); - return _FAIL; - } - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo!= NULL!!!\n", __func__); - - if (is_multicast_ether_addr(pattrib->ra)) - prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; - else - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - - for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - /* 4 the last fragment */ - if ((curfragnum + 1) == pattrib->nr_frags) { - length = pattrib->last_txcmdsz - - pattrib->hdrlen-pattrib->iv_len - - pattrib->icv_len; - - aes_cipher(prwskey, pattrib->hdrlen, pframe, length); - } else { - length = pxmitpriv->frag_len-pattrib->hdrlen - - pattrib->iv_len - pattrib->icv_len; - - aes_cipher(prwskey, pattrib->hdrlen, pframe, length); - pframe += pxmitpriv->frag_len; - pframe = PTR_ALIGN(pframe, 4); - } - } -out: - return res; -} - -static int aes_decipher(u8 *key, uint hdrlen, u8 *pframe, uint plen) -{ - static u8 message[MAX_MSG_SIZE]; - uint qc_exists, a4_exists, i, j, payload_remainder, - num_blocks, payload_index; - int res = _SUCCESS; - u8 pn_vector[6]; - u8 mic_iv[16]; - u8 mic_header1[16]; - u8 mic_header2[16]; - u8 ctr_preload[16]; - /* Intermediate Buffers */ - u8 chain_buffer[16]; - u8 aes_out[16]; - u8 padded_buffer[16]; - u8 mic[8]; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe; - u16 frsubtype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE; - - memset((void *)mic_iv, 0, 16); - memset((void *)mic_header1, 0, 16); - memset((void *)mic_header2, 0, 16); - memset((void *)ctr_preload, 0, 16); - memset((void *)chain_buffer, 0, 16); - memset((void *)aes_out, 0, 16); - memset((void *)padded_buffer, 0, 16); - - /* start to decrypt the payload */ - - num_blocks = (plen - 8) / 16; /* plen including llc, payload_length and mic) */ - - payload_remainder = (plen - 8) % 16; - - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - - if ((hdrlen == sizeof(struct ieee80211_hdr_3addr) || - (hdrlen == sizeof(struct ieee80211_qos_hdr)))) - a4_exists = 0; - else - a4_exists = 1; - - if (ieee80211_is_data(hdr->frame_control)) { - if ((frsubtype == IEEE80211_STYPE_DATA_CFACK) || - (frsubtype == IEEE80211_STYPE_DATA_CFPOLL) || - (frsubtype == IEEE80211_STYPE_DATA_CFACKPOLL)) { - qc_exists = 1; - if (hdrlen != sizeof(struct ieee80211_hdr_3addr)) - hdrlen += 2; - } else if ((frsubtype == IEEE80211_STYPE_QOS_DATA) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACK) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFPOLL) || - (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACKPOLL)) { - if (hdrlen != sizeof(struct ieee80211_hdr_3addr)) - hdrlen += 2; - qc_exists = 1; - } else { - qc_exists = 0; - } - } else { - qc_exists = 0; - } - - /* now, decrypt pframe with hdrlen offset and plen long */ - - payload_index = hdrlen + 8; /* 8 is for extiv */ - - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - pframe, pn_vector, i + 1); - - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); - - for (j = 0; j < 16; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - if (payload_remainder > 0) { - /* If there is a short final block, then pad it, - * encrypt it and copy the unpadded part back - */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, - pn_vector, num_blocks + 1); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - pframe[payload_index++] = chain_buffer[j]; - } - - /* start to calculate the mic */ - if ((hdrlen + plen + 8) <= MAX_MSG_SIZE) - memcpy(message, pframe, (hdrlen + plen + 8)); /* 8 is for ext iv len */ - - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - - construct_mic_iv(mic_iv, qc_exists, a4_exists, message, - plen - 8, pn_vector); - - construct_mic_header1(mic_header1, hdrlen, message); - construct_mic_header2(mic_header2, message, a4_exists, qc_exists); - - payload_remainder = (plen - 8) % 16; - num_blocks = (plen - 8) / 16; - - /* Find start of payload */ - payload_index = hdrlen + 8; - - /* Calculate MIC */ - aes128k128d(key, mic_iv, aes_out); - bitwise_xor(aes_out, mic_header1, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - bitwise_xor(aes_out, mic_header2, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - - for (i = 0; i < num_blocks; i++) { - bitwise_xor(aes_out, &message[payload_index], chain_buffer); - - payload_index += 16; - aes128k128d(key, chain_buffer, aes_out); - } - - /* Add on the final payload block if it needs padding */ - if (payload_remainder > 0) { - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = message[payload_index++]; - bitwise_xor(aes_out, padded_buffer, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - } - - for (j = 0 ; j < 8; j++) - mic[j] = aes_out[j]; - - /* Insert MIC into payload */ - for (j = 0; j < 8; j++) - message[payload_index + j] = mic[j]; - - payload_index = hdrlen + 8; - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - message, pn_vector, i + 1); - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &message[payload_index], chain_buffer); - for (j = 0; j < 16; j++) - message[payload_index++] = chain_buffer[j]; - } - - if (payload_remainder > 0) { - /* If there is a short final block, then pad it, - * encrypt it and copy the unpadded part back - */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - message, pn_vector, num_blocks + 1); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = message[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - message[payload_index++] = chain_buffer[j]; - } - - /* Encrypt the MIC */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, - pn_vector, 0); - - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < 8; j++) - padded_buffer[j] = message[j + hdrlen + 8 + plen - 8]; - - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < 8; j++) - message[payload_index++] = chain_buffer[j]; - - /* compare the mic */ - for (i = 0; i < 8; i++) { - if (pframe[hdrlen + 8 + plen - 8 + i] != message[hdrlen + 8 + plen - 8 + i]) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s:mic check error mic[%d]: pframe(%x) != message(%x)\n", - __func__, i, - pframe[hdrlen + 8 + plen - 8 + i], - message[hdrlen + 8 + plen - 8 + i]); - DBG_8723A("%s:mic check error mic[%d]: pframe(%x) != message(%x)\n", - __func__, i, - pframe[hdrlen + 8 + plen - 8 + i], - message[hdrlen + 8 + plen - 8 + i]); - res = _FAIL; - } - } - return res; -} - -int rtw_aes_decrypt23a(struct rtw_adapter *padapter, - struct recv_frame *precvframe) -{ /* exclude ICV */ - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &precvframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sk_buff *skb = precvframe->pkt; - int length; - u8 *pframe, *prwskey; - int res = _SUCCESS; - - pframe = skb->data; - /* 4 start to encrypt each fragment */ - if (prxattrib->encrypt != WLAN_CIPHER_SUITE_CCMP) - return _FAIL; - - stainfo = rtw_get_stainfo23a(&padapter->stapriv, &prxattrib->ta[0]); - if (!stainfo) { - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo == NULL!!!\n", __func__); - res = _FAIL; - goto exit; - } - - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "%s: stainfo!= NULL!!!\n", __func__); - - if (is_multicast_ether_addr(prxattrib->ra)) { - /* in concurrent we should use sw decrypt in - * group key, so we remove this message - */ - if (!psecuritypriv->binstallGrpkey) { - res = _FAIL; - DBG_8723A("%s:rx bc/mc packets, but didn't install " - "group key!!!!!!!!!!\n", __func__); - goto exit; - } - prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey; - if (psecuritypriv->dot118021XGrpKeyid != prxattrib->key_index) { - DBG_8723A("not match packet_index =%d, install_index =" - "%d\n", prxattrib->key_index, - psecuritypriv->dot118021XGrpKeyid); - res = _FAIL; - goto exit; - } - } else { - prwskey = &stainfo->dot118021x_UncstKey.skey[0]; - } - - length = skb->len - prxattrib->hdrlen - prxattrib->iv_len; - - res = aes_decipher(prwskey, prxattrib->hdrlen, pframe, length); -exit: - return res; -} - -void rtw_use_tkipkey_handler23a(void *function_context) -{ - struct rtw_adapter *padapter = function_context; - - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "^^^%s ^^^\n", __func__); - padapter->securitypriv.busetkipkey = 1; - RT_TRACE(_module_rtl871x_security_c_, _drv_err_, - "^^^%s padapter->securitypriv.busetkipkey =%d^^^\n", - __func__, padapter->securitypriv.busetkipkey); -} diff --git a/drivers/staging/rtl8723au/core/rtw_sreset.c b/drivers/staging/rtl8723au/core/rtw_sreset.c deleted file mode 100644 index 29a29d92a6ac..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_sreset.c +++ /dev/null @@ -1,214 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ - -#include <rtw_sreset.h> -#include <usb_ops_linux.h> - -void rtw_sreset_init(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - - mutex_init(&psrtpriv->silentreset_mutex); - psrtpriv->silent_reset_inprogress = false; - psrtpriv->last_tx_time = 0; - psrtpriv->last_tx_complete_time = 0; -} - -void rtw_sreset_reset_value(struct rtw_adapter *padapter) -{ - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - - psrtpriv->silent_reset_inprogress = false; - psrtpriv->last_tx_time = 0; - psrtpriv->last_tx_complete_time = 0; -} - -bool rtw_sreset_inprogress(struct rtw_adapter *padapter) -{ - struct rtw_adapter *primary_adapter = GET_PRIMARY_ADAPTER(padapter); - struct hal_data_8723a *pHalData = GET_HAL_DATA(primary_adapter); - - return pHalData->srestpriv.silent_reset_inprogress; -} - -static void sreset_restore_security_station(struct rtw_adapter *padapter) -{ - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info; - u8 val8; - - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) - val8 = 0xcc; - else - val8 = 0xcf; - - rtl8723a_set_sec_cfg(padapter, val8); - - if (padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_TKIP || - padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) { - psta = rtw_get_stainfo23a(pstapriv, get_bssid(mlmepriv)); - if (psta == NULL) { - /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */ - } else { - /* pairwise key */ - rtw_setstakey_cmd23a(padapter, (unsigned char *)psta, true); - /* group key */ - rtw_set_key23a(padapter,&padapter->securitypriv, padapter->securitypriv.dot118021XGrpKeyid, 0); - } - } -} - -static void sreset_restore_network_station(struct rtw_adapter *padapter) -{ - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u8 threshold; - - rtw_setopmode_cmd23a(padapter, NL80211_IFTYPE_STATION); - - /* TH = 1 => means that invalidate usb rx aggregation */ - /* TH = 0 => means that validate usb rx aggregation, use init value. */ - if (mlmepriv->htpriv.ht_option) { - if (padapter->registrypriv.wifi_spec == 1) - threshold = 1; - else - threshold = 0; - } else - threshold = 1; - - rtl8723a_set_rxdma_agg_pg_th(padapter, threshold); - - set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress); - hw_var_set_mlme_join(padapter, 0); - - rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3); - - mlmeext_joinbss_event_callback23a(padapter, 1); - /* restore Sequence No. */ - rtl8723au_write8(padapter, REG_NQOS_SEQ, padapter->xmitpriv.nqos_ssn); - - sreset_restore_security_station(padapter); -} - -static void sreset_restore_network_status(struct rtw_adapter *padapter) -{ - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - - if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) { - DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_STATION_STATE\n", - __func__, padapter->pnetdev->name, - get_fwstate(mlmepriv)); - sreset_restore_network_station(padapter); -#ifdef CONFIG_8723AU_AP_MODE - } else if (check_fwstate(mlmepriv, WIFI_AP_STATE)) { - DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_AP_STATE\n", - __func__, padapter->pnetdev->name, - get_fwstate(mlmepriv)); - rtw_ap_restore_network(padapter); -#endif - } else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE)) { - DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_ADHOC_STATE\n", - __func__, padapter->pnetdev->name, - get_fwstate(mlmepriv)); - } else { - DBG_8723A("%s(%s): fwstate:0x%08x - ???\n", __func__, - padapter->pnetdev->name, get_fwstate(mlmepriv)); - } -} - -static void sreset_stop_adapter(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (padapter == NULL) - return; - - DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name); - - if (!rtw_netif_queue_stopped(padapter->pnetdev)) - netif_tx_stop_all_queues(padapter->pnetdev); - - rtw_cancel_all_timer23a(padapter); - - /* TODO: OS and HCI independent */ - tasklet_kill(&pxmitpriv->xmit_tasklet); - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - rtw_scan_abort23a(padapter); - - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - rtw23a_join_to_handler((unsigned long)padapter); -} - -static void sreset_start_adapter(struct rtw_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (padapter == NULL) - return; - - DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) - sreset_restore_network_status(padapter); - - /* TODO: OS and HCI independent */ - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); - - mod_timer(&padapter->mlmepriv.dynamic_chk_timer, - jiffies + msecs_to_jiffies(2000)); - - if (rtw_netif_queue_stopped(padapter->pnetdev)) - netif_tx_wake_all_queues(padapter->pnetdev); -} - -void rtw_sreset_reset(struct rtw_adapter *active_adapter) -{ - struct rtw_adapter *padapter = GET_PRIMARY_ADAPTER(active_adapter); - struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - unsigned long start = jiffies; - - DBG_8723A("%s\n", __func__); - - mutex_lock(&psrtpriv->silentreset_mutex); - psrtpriv->silent_reset_inprogress = true; - pwrpriv->change_rfpwrstate = rf_off; - - sreset_stop_adapter(padapter); - - ips_enter23a(padapter); - ips_leave23a(padapter); - - sreset_start_adapter(padapter); - psrtpriv->silent_reset_inprogress = false; - mutex_unlock(&psrtpriv->silentreset_mutex); - - DBG_8723A("%s done in %d ms\n", __func__, - jiffies_to_msecs(jiffies - start)); -} diff --git a/drivers/staging/rtl8723au/core/rtw_sta_mgt.c b/drivers/staging/rtl8723au/core/rtw_sta_mgt.c deleted file mode 100644 index a9b778c45d44..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_sta_mgt.c +++ /dev/null @@ -1,439 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_STA_MGT_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <recv_osdep.h> -#include <xmit_osdep.h> -#include <mlme_osdep.h> -#include <sta_info.h> -#include <rtl8723a_hal.h> - -static const u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - -static void _rtw_init_stainfo(struct sta_info *psta) -{ - memset((u8 *)psta, 0, sizeof(struct sta_info)); - spin_lock_init(&psta->lock); - INIT_LIST_HEAD(&psta->list); - INIT_LIST_HEAD(&psta->hash_list); - _rtw_init_queue23a(&psta->sleep_q); - psta->sleepq_len = 0; - _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv); - _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv); -#ifdef CONFIG_8723AU_AP_MODE - INIT_LIST_HEAD(&psta->asoc_list); - INIT_LIST_HEAD(&psta->auth_list); - psta->expire_to = 0; - psta->flags = 0; - psta->capability = 0; - psta->bpairwise_key_installed = false; - psta->nonerp_set = 0; - psta->no_short_slot_time_set = 0; - psta->no_short_preamble_set = 0; - psta->no_ht_gf_set = 0; - psta->no_ht_set = 0; - psta->ht_20mhz_set = 0; - psta->keep_alive_trycnt = 0; -#endif /* CONFIG_8723AU_AP_MODE */ -} - -int _rtw_init_sta_priv23a(struct sta_priv *pstapriv) -{ - int i; - - spin_lock_init(&pstapriv->sta_hash_lock); - pstapriv->asoc_sta_count = 0; - for (i = 0; i < NUM_STA; i++) - INIT_LIST_HEAD(&pstapriv->sta_hash[i]); - -#ifdef CONFIG_8723AU_AP_MODE - pstapriv->sta_dz_bitmap = 0; - pstapriv->tim_bitmap = 0; - INIT_LIST_HEAD(&pstapriv->asoc_list); - INIT_LIST_HEAD(&pstapriv->auth_list); - spin_lock_init(&pstapriv->asoc_list_lock); - spin_lock_init(&pstapriv->auth_list_lock); - pstapriv->asoc_list_cnt = 0; - pstapriv->auth_list_cnt = 0; - pstapriv->auth_to = 3; /* 3*2 = 6 sec */ - pstapriv->assoc_to = 3; - /* pstapriv->expire_to = 900; 900*2 = 1800 sec = 30 min, - expire after no any traffic. */ - /* pstapriv->expire_to = 30; 30*2 = 60 sec = 1 min, - expire after no any traffic. */ - pstapriv->expire_to = 3; /* 3*2 = 6 sec */ - pstapriv->max_num_sta = NUM_STA; -#endif - return _SUCCESS; -} - -int _rtw_free_sta_priv23a(struct sta_priv *pstapriv) -{ - struct list_head *phead; - struct sta_info *psta, *ptmp; - struct recv_reorder_ctrl *preorder_ctrl; - int index; - - if (pstapriv) { - /* delete all reordering_ctrl_timer */ - spin_lock_bh(&pstapriv->sta_hash_lock); - for (index = 0; index < NUM_STA; index++) { - phead = &pstapriv->sta_hash[index]; - list_for_each_entry_safe(psta, ptmp, phead, hash_list) { - int i; - - for (i = 0; i < 16 ; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); - } - } - } - spin_unlock_bh(&pstapriv->sta_hash_lock); - /*===============================*/ - } - return _SUCCESS; -} - -struct sta_info * -rtw_alloc_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr, gfp_t gfp) -{ - struct list_head *phash_list; - struct sta_info *psta; - struct recv_reorder_ctrl *preorder_ctrl; - s32 index; - int i = 0; - u16 wRxSeqInitialValue = 0xffff; - - psta = kmalloc(sizeof(struct sta_info), gfp); - if (!psta) - return NULL; - - spin_lock_bh(&pstapriv->sta_hash_lock); - - _rtw_init_stainfo(psta); - - psta->padapter = pstapriv->padapter; - - ether_addr_copy(psta->hwaddr, hwaddr); - - index = wifi_mac_hash(hwaddr); - - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, - "rtw_alloc_stainfo23a: index = %x\n", index); - if (index >= NUM_STA) { - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, - "ERROR => rtw_alloc_stainfo23a: index >= NUM_STA\n"); - psta = NULL; - goto exit; - } - phash_list = &pstapriv->sta_hash[index]; - - list_add_tail(&psta->hash_list, phash_list); - - pstapriv->asoc_sta_count++; - -/* For the SMC router, the sequence number of first packet of WPS - handshake will be 0. */ -/* In this case, this packet will be dropped by recv_decache function - if we use the 0x00 as the default value for tid_rxseq variable. */ -/* So, we initialize the tid_rxseq variable as the 0xffff. */ - - for (i = 0; i < 16; i++) - memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], - &wRxSeqInitialValue, 2); - - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, - "alloc number_%d stainfo with hwaddr = %pM\n", - pstapriv->asoc_sta_count, hwaddr); - - init_addba_retry_timer23a(psta); - - /* for A-MPDU Rx reordering buffer control */ - for (i = 0; i < 16; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - - preorder_ctrl->padapter = pstapriv->padapter; - - preorder_ctrl->enable = false; - - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - /* preorder_ctrl->wsize_b = (NR_RECVBUFF-2); */ - preorder_ctrl->wsize_b = 64;/* 64; */ - - _rtw_init_queue23a(&preorder_ctrl->pending_recvframe_queue); - - rtw_init_recv_timer23a(preorder_ctrl); - } - /* init for DM */ - psta->rssi_stat.UndecoratedSmoothedPWDB = (-1); - psta->rssi_stat.UndecoratedSmoothedCCK = (-1); - - /* init for the sequence number of received management frame */ - psta->RxMgmtFrameSeqNum = 0xffff; -exit: - spin_unlock_bh(&pstapriv->sta_hash_lock); - return psta; -} - -/* using pstapriv->sta_hash_lock to protect */ -int rtw_free_stainfo23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct recv_reorder_ctrl *preorder_ctrl; - struct sta_xmit_priv *pstaxmitpriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct hw_xmit *phwxmit; - int i; - - if (!psta) - goto exit; - - spin_lock_bh(&psta->lock); - psta->state &= ~_FW_LINKED; - spin_unlock_bh(&psta->lock); - - pstaxmitpriv = &psta->sta_xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - - rtw_free_xmitframe_queue23a(pxmitpriv, &psta->sleep_q); - psta->sleepq_len = 0; - - /* vo */ - rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); - list_del_init(&pstaxmitpriv->vo_q.tx_pending); - phwxmit = pxmitpriv->hwxmits; - phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt; - pstaxmitpriv->vo_q.qcnt = 0; - - /* vi */ - rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); - list_del_init(&pstaxmitpriv->vi_q.tx_pending); - phwxmit = pxmitpriv->hwxmits+1; - phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt; - pstaxmitpriv->vi_q.qcnt = 0; - - /* be */ - rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->be_q.sta_pending); - list_del_init(&pstaxmitpriv->be_q.tx_pending); - phwxmit = pxmitpriv->hwxmits+2; - phwxmit->accnt -= pstaxmitpriv->be_q.qcnt; - pstaxmitpriv->be_q.qcnt = 0; - - /* bk */ - rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); - list_del_init(&pstaxmitpriv->bk_q.tx_pending); - phwxmit = pxmitpriv->hwxmits+3; - phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt; - pstaxmitpriv->bk_q.qcnt = 0; - - spin_unlock_bh(&pxmitpriv->lock); - - list_del_init(&psta->hash_list); - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, - "free number_%d stainfo with hwaddr = %pM\n", - pstapriv->asoc_sta_count, psta->hwaddr); - pstapriv->asoc_sta_count--; - - /* re-init sta_info; 20061114 will be init in alloc_stainfo */ - /* _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv); */ - /* _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv); */ - - del_timer_sync(&psta->addba_retry_timer); - - /* for A-MPDU Rx reordering buffer control, - cancel reordering_ctrl_timer */ - for (i = 0; i < 16; i++) { - struct list_head *phead, *plist; - struct recv_frame *prframe; - struct rtw_queue *ppending_recvframe_queue; - - preorder_ctrl = &psta->recvreorder_ctrl[i]; - - del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); - - ppending_recvframe_queue = - &preorder_ctrl->pending_recvframe_queue; - - spin_lock_bh(&ppending_recvframe_queue->lock); - phead = get_list_head(ppending_recvframe_queue); - plist = phead->next; - - while (!list_empty(phead)) { - prframe = container_of(plist, struct recv_frame, list); - plist = plist->next; - list_del_init(&prframe->list); - rtw_free_recvframe23a(prframe); - } - spin_unlock_bh(&ppending_recvframe_queue->lock); - } - if (!(psta->state & WIFI_AP_STATE)) - rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, false); -#ifdef CONFIG_8723AU_AP_MODE - spin_lock_bh(&pstapriv->auth_list_lock); - if (!list_empty(&psta->auth_list)) { - list_del_init(&psta->auth_list); - pstapriv->auth_list_cnt--; - } - spin_unlock_bh(&pstapriv->auth_list_lock); - - psta->expire_to = 0; - - psta->sleepq_ac_len = 0; - psta->qos_info = 0; - - psta->max_sp_len = 0; - psta->uapsd_bk = 0; - psta->uapsd_be = 0; - psta->uapsd_vi = 0; - psta->uapsd_vo = 0; - - psta->has_legacy_ac = 0; - - pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid); - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - - if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) { - pstapriv->sta_aid[psta->aid - 1] = NULL; - psta->aid = 0; - } -#endif /* CONFIG_8723AU_AP_MODE */ - - kfree(psta); -exit: - return _SUCCESS; -} - -/* free all stainfo which in sta_hash[all] */ -void rtw_free_all_stainfo23a(struct rtw_adapter *padapter) -{ - struct list_head *phead; - struct sta_info *psta, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo23a(padapter); - s32 index; - - if (pstapriv->asoc_sta_count == 1) - return; - - spin_lock_bh(&pstapriv->sta_hash_lock); - for (index = 0; index < NUM_STA; index++) { - phead = &pstapriv->sta_hash[index]; - list_for_each_entry_safe(psta, ptmp, phead, hash_list) { - if (pbcmc_stainfo != psta) - rtw_free_stainfo23a(padapter, psta); - } - } - spin_unlock_bh(&pstapriv->sta_hash_lock); -} - -/* any station allocated can be searched by hash list */ -struct sta_info *rtw_get_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr) -{ - struct list_head *phead; - struct sta_info *pos, *psta = NULL; - u32 index; - const u8 *addr; - - if (!hwaddr) - return NULL; - - if (is_multicast_ether_addr(hwaddr)) - addr = bc_addr; - else - addr = hwaddr; - - index = wifi_mac_hash(addr); - - spin_lock_bh(&pstapriv->sta_hash_lock); - phead = &pstapriv->sta_hash[index]; - list_for_each_entry(pos, phead, hash_list) { - psta = pos; - - /* if found the matched address */ - if (ether_addr_equal(psta->hwaddr, addr)) - break; - - psta = NULL; - } - spin_unlock_bh(&pstapriv->sta_hash_lock); - return psta; -} - -int rtw_init_bcmc_stainfo23a(struct rtw_adapter *padapter) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - struct tx_servq *ptxservq; - int res = _SUCCESS; - - psta = rtw_alloc_stainfo23a(pstapriv, bc_addr, GFP_KERNEL); - if (!psta) { - res = _FAIL; - RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, - "rtw_alloc_stainfo23a fail\n"); - return res; - } - /* default broadcast & multicast use macid 1 */ - psta->mac_id = 1; - - ptxservq = &psta->sta_xmitpriv.be_q; - return _SUCCESS; -} - -struct sta_info *rtw_get_bcmc_stainfo23a(struct rtw_adapter *padapter) -{ - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - psta = rtw_get_stainfo23a(pstapriv, bc_addr); - return psta; -} - -bool rtw_access_ctrl23a(struct rtw_adapter *padapter, u8 *mac_addr) -{ - bool res = true; -#ifdef CONFIG_8723AU_AP_MODE - struct list_head *phead; - struct rtw_wlan_acl_node *paclnode; - bool match = false; - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q; - - spin_lock_bh(&pacl_node_q->lock); - phead = get_list_head(pacl_node_q); - list_for_each_entry(paclnode, phead, list) { - if (ether_addr_equal(paclnode->addr, mac_addr)) { - if (paclnode->valid) { - match = true; - break; - } - } - } - spin_unlock_bh(&pacl_node_q->lock); - - if (pacl_list->mode == 1)/* accept unless in deny list */ - res = (match) ? false : true; - else if (pacl_list->mode == 2)/* deny unless in accept list */ - res = (match) ? true : false; - else - res = true; -#endif - return res; -} diff --git a/drivers/staging/rtl8723au/core/rtw_wlan_util.c b/drivers/staging/rtl8723au/core/rtw_wlan_util.c deleted file mode 100644 index 694cf17f82cf..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_wlan_util.c +++ /dev/null @@ -1,1537 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_WLAN_UTIL_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <linux/ieee80211.h> -#include <wifi.h> -#include <rtl8723a_spec.h> - -static unsigned char ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f}; -static unsigned char ARTHEROS_OUI2[] = {0x00, 0x13, 0x74}; - -static unsigned char BROADCOM_OUI1[] = {0x00, 0x10, 0x18}; -static unsigned char BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7}; - -static unsigned char CISCO_OUI[] = {0x00, 0x40, 0x96}; -static unsigned char MARVELL_OUI[] = {0x00, 0x50, 0x43}; -static unsigned char RALINK_OUI[] = {0x00, 0x0c, 0x43}; -static unsigned char REALTEK_OUI[] = {0x00, 0xe0, 0x4c}; -static unsigned char AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5}; -static unsigned char EPIGRAM_OUI[] = {0x00, 0x90, 0x4c}; - -static unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02}; -static unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02}; - -#define R2T_PHY_DELAY 0 - -/* define WAIT_FOR_BCN_TO_MIN 3000 */ -#define WAIT_FOR_BCN_TO_MIN 6000 -#define WAIT_FOR_BCN_TO_MAX 20000 - -static u8 rtw_basic_rate_cck[4] = { - IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK -}; - -static u8 rtw_basic_rate_ofdm[3] = { - IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK -}; - -static u8 rtw_basic_rate_mix[7] = { - IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK, - IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK -}; - -int cckrates_included23a(unsigned char *rate, int ratelen) -{ - int i; - - for (i = 0; i < ratelen; i++) { - if (((rate[i]) & 0x7f) == 2 || ((rate[i]) & 0x7f) == 4 || - ((rate[i]) & 0x7f) == 11 || ((rate[i]) & 0x7f) == 22) - return true; - } - - return false; -} - -int cckratesonly_included23a(unsigned char *rate, int ratelen) -{ - int i; - - for (i = 0; i < ratelen; i++) { - if (((rate[i]) & 0x7f) != 2 && ((rate[i]) & 0x7f) != 4 && - ((rate[i]) & 0x7f) != 11 && ((rate[i]) & 0x7f) != 22) - return false; - } - - return true; -} - -unsigned char networktype_to_raid23a(unsigned char network_type) -{ - unsigned char raid; - - switch (network_type) { - case WIRELESS_11B: - raid = RATR_INX_WIRELESS_B; - break; - case WIRELESS_11A: - case WIRELESS_11G: - raid = RATR_INX_WIRELESS_G; - break; - case WIRELESS_11BG: - raid = RATR_INX_WIRELESS_GB; - break; - case WIRELESS_11_24N: - case WIRELESS_11_5N: - raid = RATR_INX_WIRELESS_N; - break; - case WIRELESS_11A_5N: - case WIRELESS_11G_24N: - raid = RATR_INX_WIRELESS_NG; - break; - case WIRELESS_11BG_24N: - raid = RATR_INX_WIRELESS_NGB; - break; - default: - raid = RATR_INX_WIRELESS_GB; - break; - } - return raid; -} - -u8 judge_network_type23a(struct rtw_adapter *padapter, - unsigned char *rate, int ratelen) -{ - u8 network_type = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeext->cur_channel > 14) { - if (pmlmeinfo->HT_enable) - network_type = WIRELESS_11_5N; - network_type |= WIRELESS_11A; - } else { - if (pmlmeinfo->HT_enable) - network_type = WIRELESS_11_24N; - - if ((cckratesonly_included23a(rate, ratelen)) == true) - network_type |= WIRELESS_11B; - else if ((cckrates_included23a(rate, ratelen)) == true) - network_type |= WIRELESS_11BG; - else - network_type |= WIRELESS_11G; - } - return network_type; -} - -static unsigned char ratetbl_val_2wifirate(unsigned char rate) -{ - unsigned char val = 0; - - switch (rate & 0x7f) { - case 0: - val = IEEE80211_CCK_RATE_1MB; - break; - case 1: - val = IEEE80211_CCK_RATE_2MB; - break; - case 2: - val = IEEE80211_CCK_RATE_5MB; - break; - case 3: - val = IEEE80211_CCK_RATE_11MB; - break; - case 4: - val = IEEE80211_OFDM_RATE_6MB; - break; - case 5: - val = IEEE80211_OFDM_RATE_9MB; - break; - case 6: - val = IEEE80211_OFDM_RATE_12MB; - break; - case 7: - val = IEEE80211_OFDM_RATE_18MB; - break; - case 8: - val = IEEE80211_OFDM_RATE_24MB; - break; - case 9: - val = IEEE80211_OFDM_RATE_36MB; - break; - case 10: - val = IEEE80211_OFDM_RATE_48MB; - break; - case 11: - val = IEEE80211_OFDM_RATE_54MB; - break; - } - return val; -} - -static int is_basicrate(struct rtw_adapter *padapter, unsigned char rate) -{ - int i; - unsigned char val; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - for (i = 0; i < NumRates; i++) { - val = pmlmeext->basicrate[i]; - - if (val != 0xff && val != 0xfe) { - if (rate == ratetbl_val_2wifirate(val)) - return true; - } - } - - return false; -} - -static unsigned int ratetbl2rateset(struct rtw_adapter *padapter, - unsigned char *rateset) -{ - int i; - unsigned char rate; - unsigned int len = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - for (i = 0; i < NumRates; i++) { - rate = pmlmeext->datarate[i]; - - switch (rate) { - case 0xff: - return len; - case 0xfe: - continue; - default: - rate = ratetbl_val_2wifirate(rate); - - if (is_basicrate(padapter, rate) == true) - rate |= IEEE80211_BASIC_RATE_MASK; - - rateset[len] = rate; - len++; - break; - } - } - return len; -} - -void get_rate_set23a(struct rtw_adapter *padapter, - unsigned char *pbssrate, int *bssrate_len) -{ - unsigned char supportedrates[NumRates]; - - memset(supportedrates, 0, NumRates); - *bssrate_len = ratetbl2rateset(padapter, supportedrates); - memcpy(pbssrate, supportedrates, *bssrate_len); -} - -void UpdateBrateTbl23a(struct rtw_adapter *Adapter, u8 *mBratesOS) -{ - u8 i; - u8 rate; - - /* 1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */ - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - rate = mBratesOS[i] & 0x7f; - switch (rate) { - case IEEE80211_CCK_RATE_1MB: - case IEEE80211_CCK_RATE_2MB: - case IEEE80211_CCK_RATE_5MB: - case IEEE80211_CCK_RATE_11MB: - case IEEE80211_OFDM_RATE_6MB: - case IEEE80211_OFDM_RATE_12MB: - case IEEE80211_OFDM_RATE_24MB: - mBratesOS[i] |= IEEE80211_BASIC_RATE_MASK; - break; - default: - break; - } - } -} - -void Update23aTblForSoftAP(u8 *bssrateset, u32 bssratelen) -{ - u8 i; - u8 rate; - - for (i = 0; i < bssratelen; i++) { - rate = bssrateset[i] & 0x7f; - switch (rate) { - case IEEE80211_CCK_RATE_1MB: - case IEEE80211_CCK_RATE_2MB: - case IEEE80211_CCK_RATE_5MB: - case IEEE80211_CCK_RATE_11MB: - bssrateset[i] |= IEEE80211_BASIC_RATE_MASK; - break; - } - } -} - -inline u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter) -{ - return adapter_to_dvobj(adapter)->oper_channel; -} - -inline void rtw_set_oper_ch23a(struct rtw_adapter *adapter, u8 ch) -{ - adapter_to_dvobj(adapter)->oper_channel = ch; -} - -inline void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw) -{ - adapter_to_dvobj(adapter)->oper_bwmode = bw; -} - -inline void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 offset) -{ - adapter_to_dvobj(adapter)->oper_ch_offset = offset; -} - -void SelectChannel23a(struct rtw_adapter *padapter, unsigned char channel) -{ - mutex_lock(&adapter_to_dvobj(padapter)->setch_mutex); - - /* saved channel info */ - rtw_set_oper_ch23a(padapter, channel); - - PHY_SwChnl8723A(padapter, channel); - - mutex_unlock(&adapter_to_dvobj(padapter)->setch_mutex); -} - -static void set_bwmode(struct rtw_adapter *padapter, unsigned short bwmode, - unsigned char channel_offset) -{ - mutex_lock(&adapter_to_dvobj(padapter)->setbw_mutex); - - /* saved bw info */ - rtw_set_oper_bw23a(padapter, bwmode); - rtw_set_oper_ch23aoffset23a(padapter, channel_offset); - - PHY_SetBWMode23a8723A(padapter, (enum ht_channel_width)bwmode, - channel_offset); - - mutex_unlock(&adapter_to_dvobj(padapter)->setbw_mutex); -} - -void set_channel_bwmode23a(struct rtw_adapter *padapter, unsigned char channel, - unsigned char channel_offset, unsigned short bwmode) -{ - u8 center_ch; - - if (bwmode == HT_CHANNEL_WIDTH_20 || - channel_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) { - /* SelectChannel23a(padapter, channel); */ - center_ch = channel; - } else { - /* switch to the proper channel */ - if (channel_offset == HAL_PRIME_CHNL_OFFSET_LOWER) { - /* SelectChannel23a(padapter, channel + 2); */ - center_ch = channel + 2; - } else { - /* SelectChannel23a(padapter, channel - 2); */ - center_ch = channel - 2; - } - } - - /* set Channel */ - mutex_lock(&adapter_to_dvobj(padapter)->setch_mutex); - - /* saved channel/bw info */ - rtw_set_oper_ch23a(padapter, channel); - rtw_set_oper_bw23a(padapter, bwmode); - rtw_set_oper_ch23aoffset23a(padapter, channel_offset); - - PHY_SwChnl8723A(padapter, center_ch); /* set center channel */ - - mutex_unlock(&adapter_to_dvobj(padapter)->setch_mutex); - - set_bwmode(padapter, bwmode, channel_offset); -} - -inline u8 *get_my_bssid23a(struct wlan_bssid_ex *pnetwork) -{ - return pnetwork->MacAddress; -} - -bool is_client_associated_to_ap23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - - if (!padapter) - return false; - - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS && - (pmlmeinfo->state & 0x03) == MSR_INFRA) - return true; - else - return false; -} - -bool is_client_associated_to_ibss23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS && - (pmlmeinfo->state & 0x03) == MSR_ADHOC) - return true; - else - return false; -} - -bool is_IBSS_empty23a(struct rtw_adapter *padapter) -{ - unsigned int i; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) { - if (pmlmeinfo->FW_sta_info[i].status == 1) - return false; - } - - return true; -} - -unsigned int decide_wait_for_beacon_timeout23a(unsigned int bcn_interval) -{ - if ((bcn_interval << 2) < WAIT_FOR_BCN_TO_MIN) - return WAIT_FOR_BCN_TO_MIN; - else if ((bcn_interval << 2) > WAIT_FOR_BCN_TO_MAX) - return WAIT_FOR_BCN_TO_MAX; - else - return bcn_interval << 2; -} - -void clear_cam_entry23a(struct rtw_adapter *padapter, u8 entry) -{ - unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - unsigned char null_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}; - - rtl8723a_cam_write(padapter, entry, 0, null_sta, null_key); -} - -int allocate_fw_sta_entry23a(struct rtw_adapter *padapter) -{ - unsigned int mac_id; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - for (mac_id = IBSS_START_MAC_ID; mac_id < NUM_STA; mac_id++) { - if (pmlmeinfo->FW_sta_info[mac_id].status == 0) { - pmlmeinfo->FW_sta_info[mac_id].status = 1; - pmlmeinfo->FW_sta_info[mac_id].retry = 0; - break; - } - } - - return mac_id; -} - -void flush_all_cam_entry23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - rtl8723a_cam_invalidate_all(padapter); - - memset(pmlmeinfo->FW_sta_info, 0, sizeof(pmlmeinfo->FW_sta_info)); -} - -int WMM_param_handler23a(struct rtw_adapter *padapter, const u8 *p) -{ - /* struct registry_priv *pregpriv = &padapter->registrypriv; */ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmepriv->qos_option == 0) { - pmlmeinfo->WMM_enable = 0; - return _FAIL; - } - - pmlmeinfo->WMM_enable = 1; - memcpy(&pmlmeinfo->WMM_param, p + 2 + 6, - sizeof(struct WMM_para_element)); - return true; -} - -void WMMOnAssocRsp23a(struct rtw_adapter *padapter) -{ - u8 ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime; - u8 acm_mask; - u16 TXOP; - u32 acParm, i; - u32 edca[4], inx[4]; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct registry_priv *pregpriv = &padapter->registrypriv; - - if (pmlmeinfo->WMM_enable == 0) { - padapter->mlmepriv.acm_mask = 0; - return; - } - - acm_mask = 0; - - if (pmlmeext->cur_wireless_mode == WIRELESS_11B) - aSifsTime = 10; - else - aSifsTime = 16; - - for (i = 0; i < 4; i++) { - ACI = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 5) & 0x03; - ACM = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 4) & 0x01; - - /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */ - AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) * - pmlmeinfo->slotTime + aSifsTime; - - ECWMin = pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f; - ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4; - TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit); - - acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); - - switch (ACI) { - case 0x0: - rtl8723a_set_ac_param_be(padapter, acParm); - acm_mask |= (ACM? BIT(1):0); - edca[XMIT_BE_QUEUE] = acParm; - break; - case 0x1: - rtl8723a_set_ac_param_bk(padapter, acParm); - /* acm_mask |= (ACM? BIT(0):0); */ - edca[XMIT_BK_QUEUE] = acParm; - break; - case 0x2: - rtl8723a_set_ac_param_vi(padapter, acParm); - acm_mask |= (ACM? BIT(2):0); - edca[XMIT_VI_QUEUE] = acParm; - break; - case 0x3: - rtl8723a_set_ac_param_vo(padapter, acParm); - acm_mask |= (ACM? BIT(3):0); - edca[XMIT_VO_QUEUE] = acParm; - break; - } - - DBG_8723A("WMM(%x): %x, %x\n", ACI, ACM, acParm); - } - - if (padapter->registrypriv.acm_method == 1) - rtl8723a_set_acm_ctrl(padapter, acm_mask); - else - padapter->mlmepriv.acm_mask = acm_mask; - - inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3; - - if (pregpriv->wifi_spec == 1) { - u32 j, change_inx = false; - - /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */ - for (i = 0; i < 4; i++) { - for (j = i+1; j < 4; j++) { - /* compare CW and AIFS */ - if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) { - change_inx = true; - } else if ((edca[j] & 0xFFFF) == - (edca[i] & 0xFFFF)) { - /* compare TXOP */ - if ((edca[j] >> 16) > (edca[i] >> 16)) - change_inx = true; - } - - if (change_inx) { - swap(edca[i], edca[j]); - swap(inx[i], inx[j]); - change_inx = false; - } - } - } - } - - for (i = 0; i<4; i++) { - pxmitpriv->wmm_para_seq[i] = inx[i]; - DBG_8723A("wmm_para_seq(%d): %d\n", i, - pxmitpriv->wmm_para_seq[i]); - } -} - -static void bwmode_update_check(struct rtw_adapter *padapter, const u8 *p) -{ - struct ieee80211_ht_operation *pHT_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - unsigned char new_bwmode; - unsigned char new_ch_offset; - - if (!p) - return; - if (!phtpriv->ht_option) - return; - if (p[1] != sizeof(struct ieee80211_ht_operation)) - return; - - pHT_info = (struct ieee80211_ht_operation *)(p + 2); - - if ((pHT_info->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) && - pregistrypriv->cbw40_enable) { - new_bwmode = HT_CHANNEL_WIDTH_40; - - switch (pHT_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET){ - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - break; - default: - new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - } else { - new_bwmode = HT_CHANNEL_WIDTH_20; - new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - - if (new_bwmode != pmlmeext->cur_bwmode || - new_ch_offset != pmlmeext->cur_ch_offset) { - pmlmeinfo->bwmode_updated = true; - - pmlmeext->cur_bwmode = new_bwmode; - pmlmeext->cur_ch_offset = new_ch_offset; - - /* update HT info also */ - HT_info_handler23a(padapter, p); - } else - pmlmeinfo->bwmode_updated = false; - - if (pmlmeinfo->bwmode_updated) { - struct sta_info *psta; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */ - - /* update ap's stainfo */ - psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress); - if (psta) { - struct ht_priv *phtpriv_sta = &psta->htpriv; - - if (phtpriv_sta->ht_option) { - /* bwmode */ - phtpriv_sta->bwmode = pmlmeext->cur_bwmode; - phtpriv_sta->ch_offset = - pmlmeext->cur_ch_offset; - } else { - phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20; - phtpriv_sta->ch_offset = - HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - } - } -} - -void HT_caps_handler23a(struct rtw_adapter *padapter, const u8 *p) -{ - unsigned int i; - u8 rf_type; - u8 max_AMPDU_len, min_MPDU_spacing; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - struct ieee80211_ht_cap *cap; - u8 *dstcap; - - if (!p) - return; - - if (!phtpriv->ht_option) - return; - - pmlmeinfo->HT_caps_enable = 1; - - cap = &pmlmeinfo->ht_cap; - dstcap = (u8 *)cap; - for (i = 0; i < p[1]; i++) { - if (i != 2) { - dstcap[i] &= p[i + 2]; - } else { - /* modify from fw by Thomas 2010/11/17 */ - if ((cap->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR) > - (p[i + 2] & IEEE80211_HT_AMPDU_PARM_FACTOR)) - max_AMPDU_len = p[i + 2] & - IEEE80211_HT_AMPDU_PARM_FACTOR; - else - max_AMPDU_len = cap->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR; - - if ((cap->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_DENSITY) > - (p[i + 2] & IEEE80211_HT_AMPDU_PARM_DENSITY)) - min_MPDU_spacing = cap->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_DENSITY; - else - min_MPDU_spacing = p[i + 2] & - IEEE80211_HT_AMPDU_PARM_DENSITY; - - cap->ampdu_params_info = - max_AMPDU_len | min_MPDU_spacing; - } - } - - rf_type = rtl8723a_get_rf_type(padapter); - - /* update the MCS rates */ - for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { - if (rf_type == RF_1T1R || rf_type == RF_1T2R) - cap->mcs.rx_mask[i] &= MCS_rate_1R23A[i]; - else - cap->mcs.rx_mask[i] &= MCS_rate_2R23A[i]; - } -} - -void HT_info_handler23a(struct rtw_adapter *padapter, const u8 *p) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - if (!p) - return; - - if (!phtpriv->ht_option) - return; - - if (p[1] != sizeof(struct ieee80211_ht_operation)) - return; - - pmlmeinfo->HT_info_enable = 1; - memcpy(&pmlmeinfo->HT_info, p + 2, p[1]); -} - -void HTOnAssocRsp23a(struct rtw_adapter *padapter) -{ - unsigned char max_AMPDU_len; - unsigned char min_MPDU_spacing; - /* struct registry_priv *pregpriv = &padapter->registrypriv; */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - DBG_8723A("%s\n", __func__); - - if (pmlmeinfo->HT_info_enable && pmlmeinfo->HT_caps_enable) - pmlmeinfo->HT_enable = 1; - else { - pmlmeinfo->HT_enable = 0; - /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */ - return; - } - - /* handle A-MPDU parameter field */ - /* - AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k - AMPDU_para [4:2]:Min MPDU Start Spacing - */ - max_AMPDU_len = pmlmeinfo->ht_cap.ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR; - - min_MPDU_spacing = - (pmlmeinfo->ht_cap.ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2; - - rtl8723a_set_ampdu_min_space(padapter, min_MPDU_spacing); - rtl8723a_set_ampdu_factor(padapter, max_AMPDU_len); -} - -void ERP_IE_handler23a(struct rtw_adapter *padapter, const u8 *p) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (p[1] > 1) - return; - - pmlmeinfo->ERP_enable = 1; - memcpy(&pmlmeinfo->ERP_IE, p + 2, p[1]); -} - -void VCS_update23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - switch (pregpriv->vrtl_carrier_sense) { /* 0:off 1:on 2:auto */ - case 0: /* off */ - psta->rtsen = 0; - psta->cts2self = 0; - break; - case 1: /* on */ - if (pregpriv->vcs_type == RTS_CTS) { - psta->rtsen = 1; - psta->cts2self = 0; - } else { - psta->rtsen = 0; - psta->cts2self = 1; - } - break; - case 2: /* auto */ - default: - if (pmlmeinfo->ERP_enable && pmlmeinfo->ERP_IE & BIT(1)) { - if (pregpriv->vcs_type == RTS_CTS) { - psta->rtsen = 1; - psta->cts2self = 0; - } else { - psta->rtsen = 0; - psta->cts2self = 1; - } - } else { - psta->rtsen = 0; - psta->cts2self = 0; - } - break; - } -} - -int rtw_check_bcn_info23a(struct rtw_adapter *Adapter, - struct ieee80211_mgmt *mgmt, u32 pkt_len) -{ - struct wlan_network *cur_network = &Adapter->mlmepriv.cur_network; - struct ieee80211_ht_operation *pht_info; - unsigned short val16; - u8 crypto, bcn_channel; - int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0, r; - int pie_len, ssid_len, privacy; - const u8 *p, *ssid; - - if (!is_client_associated_to_ap23a(Adapter)) - return _SUCCESS; - - if (unlikely(!ieee80211_is_beacon(mgmt->frame_control))) { - printk(KERN_WARNING "%s: received a non beacon frame!\n", - __func__); - return _FAIL; - } - - if (!ether_addr_equal(cur_network->network.MacAddress, mgmt->bssid)) { - DBG_8723A("%s: linked but recv other bssid bcn %pM %pM\n", - __func__, mgmt->bssid, - cur_network->network.MacAddress); - return _FAIL; - } - - /* check bw and channel offset */ - /* parsing HT_CAP_IE */ - pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - - /* Checking for channel */ - p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable, - pie_len); - if (p) - bcn_channel = p[2]; - else { - /* In 5G, some ap do not have DSSET IE checking HT - info for channel */ - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, - mgmt->u.beacon.variable, pie_len); - - if (p && p[1] > 0) { - pht_info = (struct ieee80211_ht_operation *)(p + 2); - bcn_channel = pht_info->primary_chan; - } else { /* we don't find channel IE, so don't check it */ - DBG_8723A("Oops: %s we don't find channel IE, so don't " - "check it\n", __func__); - bcn_channel = Adapter->mlmeextpriv.cur_channel; - } - } - if (bcn_channel != Adapter->mlmeextpriv.cur_channel) { - DBG_8723A("%s beacon channel:%d cur channel:%d disconnect\n", - __func__, bcn_channel, - Adapter->mlmeextpriv.cur_channel); - goto _mismatch; - } - - /* checking SSID */ - p = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.beacon.variable, pie_len); - if (p && p[1]) { - ssid = p + 2; - ssid_len = p[1]; - } else { - DBG_8723A("%s marc: cannot find SSID for survey event\n", - __func__); - ssid = NULL; - ssid_len = 0; - } - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d cur_network->network.Ssid.Ssid:%s len:%d\n", - __func__, ssid, ssid_len, cur_network->network.Ssid.ssid, - cur_network->network.Ssid.ssid_len); - - if (ssid_len != cur_network->network.Ssid.ssid_len || ssid_len > 32 || - (ssid_len && - memcmp(ssid, cur_network->network.Ssid.ssid, ssid_len))) { - DBG_8723A("%s(), SSID is not match return FAIL\n", __func__); - goto _mismatch; - } - - /* check encryption info */ - val16 = le16_to_cpu(mgmt->u.beacon.capab_info); - - if (val16 & WLAN_CAPABILITY_PRIVACY) - privacy = 1; - else - privacy = 0; - - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s(): cur_network->network.Privacy is %d, bssid.Privacy is %d\n", - __func__, cur_network->network.Privacy, privacy); - if (cur_network->network.Privacy != privacy) { - DBG_8723A("%s(), privacy is not match return FAIL\n", __func__); - goto _mismatch; - } - - p = cfg80211_find_ie(WLAN_EID_RSN, mgmt->u.beacon.variable, pie_len); - if (p && p[1]) { - crypto = ENCRYP_PROTOCOL_WPA2; - if (p && p[1]) { - r = rtw_parse_wpa2_ie23a(p, p[1] + 2, &group_cipher, - &pairwise_cipher, &is_8021x); - if (r == _SUCCESS) - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher: %d, is_802x : %d\n", - __func__, pairwise_cipher, - group_cipher, is_8021x); - } - } else { - p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - mgmt->u.beacon.variable, pie_len); - if (p && p[1]) { - crypto = ENCRYP_PROTOCOL_WPA; - r = rtw_parse_wpa_ie23a(p, p[1] + 2, &group_cipher, - &pairwise_cipher, &is_8021x); - if (r == _SUCCESS) - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - "%s pnetwork->pairwise_cipher: %d, group_cipher is %d, is_8021x is %d\n", - __func__, pairwise_cipher, - group_cipher, is_8021x); - } else { - if (privacy) - crypto = ENCRYP_PROTOCOL_WEP; - else - crypto = ENCRYP_PROTOCOL_OPENSYS; - } - } - - if (cur_network->BcnInfo.encryp_protocol != crypto) { - DBG_8723A("%s(): encryption mismatch, return FAIL\n", __func__); - goto _mismatch; - } - - if (crypto == ENCRYP_PROTOCOL_WPA || crypto == ENCRYP_PROTOCOL_WPA2) { - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, - "%s cur_network->group_cipher is %d: %d\n", __func__, - cur_network->BcnInfo.group_cipher, group_cipher); - if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || - group_cipher != cur_network->BcnInfo.group_cipher) { - DBG_8723A("%s pairwise_cipher(%x:%x) or group_cipher " - "(%x:%x) is not match, return FAIL\n", - __func__, pairwise_cipher, - cur_network->BcnInfo.pairwise_cipher, - group_cipher, - cur_network->BcnInfo.group_cipher); - goto _mismatch; - } - - if (is_8021x != cur_network->BcnInfo.is_8021x) { - DBG_8723A("%s authentication is not match, return " - "FAIL\n", __func__); - goto _mismatch; - } - } - - return _SUCCESS; - -_mismatch: - - return _FAIL; -} - -void update_beacon23a_info(struct rtw_adapter *padapter, - struct ieee80211_mgmt *mgmt, - uint pkt_len, struct sta_info *psta) -{ - unsigned int len; - const u8 *p; - - len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - - p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, mgmt->u.beacon.variable, - len); - if (p) - bwmode_update_check(padapter, p); - - p = cfg80211_find_ie(WLAN_EID_ERP_INFO, mgmt->u.beacon.variable, len); - if (p) { - ERP_IE_handler23a(padapter, p); - VCS_update23a(padapter, psta); - } -} - -bool is_ap_in_tkip23a(struct rtw_adapter *padapter) -{ - u32 i; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - const u8 *p; - - if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) { - for (i = 0; i < pmlmeinfo->network.IELength;) { - p = pmlmeinfo->network.IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) && - !memcmp(p + 2 + 12, WPA_TKIP_CIPHER, 4)) - return true; - break; - case WLAN_EID_RSN: - if (!memcmp(p + 2 + 8, RSN_TKIP_CIPHER, 4)) - return true; - break; - default: - break; - } - i += (p[1] + 2); - } - return false; - } else - return false; -} - -bool should_forbid_n_rate23a(struct rtw_adapter *padapter) -{ - u32 i; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *cur_network = &pmlmepriv->cur_network.network; - const u8 *p; - - if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) { - for (i = 0; i < cur_network->IELength;) { - p = cur_network->IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) && - (!memcmp(p + 2 + 12, - WPA_CIPHER_SUITE_CCMP23A, 4) || - !memcmp(p + 2 + 16, - WPA_CIPHER_SUITE_CCMP23A, 4))) - return false; - break; - case WLAN_EID_RSN: - if (!memcmp(p + 2 + 8, - RSN_CIPHER_SUITE_CCMP23A, 4) || - !memcmp(p + 2 + 12, - RSN_CIPHER_SUITE_CCMP23A, 4)) - return false; - default: - break; - } - - i += (p[1] + 2); - } - return true; - } else { - return false; - } -} - -bool is_ap_in_wep23a(struct rtw_adapter *padapter) -{ - u32 i; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - const u8 *p; - - if (cur_network->capability & WLAN_CAPABILITY_PRIVACY) { - for (i = 0; i < pmlmeinfo->network.IELength;) { - p = pmlmeinfo->network.IEs + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4)) - return false; - break; - case WLAN_EID_RSN: - return false; - - default: - break; - } - - i += (p[1] + 2); - } - - return true; - } else - return false; -} - -static int wifirate2_ratetbl_inx23a(unsigned char rate) -{ - int inx = 0; - - rate = rate & 0x7f; - - switch (rate) { - case 54*2: - inx = 11; - break; - case 48*2: - inx = 10; - break; - case 36*2: - inx = 9; - break; - case 24*2: - inx = 8; - break; - case 18*2: - inx = 7; - break; - case 12*2: - inx = 6; - break; - case 9*2: - inx = 5; - break; - case 6*2: - inx = 4; - break; - case 11*2: - inx = 3; - break; - case 11: - inx = 2; - break; - case 2*2: - inx = 1; - break; - case 1*2: - inx = 0; - break; - } - return inx; -} - -unsigned int update_basic_rate23a(unsigned char *ptn, unsigned int ptn_sz) -{ - unsigned int i, num_of_rate; - unsigned int mask = 0; - - num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz; - - for (i = 0; i < num_of_rate; i++) { - if ((*(ptn + i)) & 0x80) - mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i)); - } - return mask; -} - -unsigned int update_supported_rate23a(unsigned char *ptn, unsigned int ptn_sz) -{ - unsigned int i, num_of_rate; - unsigned int mask = 0; - - num_of_rate = (ptn_sz > NumRates) ? NumRates : ptn_sz; - - for (i = 0; i < num_of_rate; i++) - mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i)); - return mask; -} - -unsigned int update_MSC_rate23a(struct ieee80211_ht_cap *pHT_caps) -{ - unsigned int mask; - - mask = pHT_caps->mcs.rx_mask[0] << 12 | - pHT_caps->mcs.rx_mask[1] << 20; - - return mask; -} - -int support_short_GI23a(struct rtw_adapter *padapter, - struct ieee80211_ht_cap *pHT_caps) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - unsigned char bit_offset; - - if (!pmlmeinfo->HT_enable) - return _FAIL; - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK) - return _FAIL; - bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40)? 6: 5; - - if (pHT_caps->cap_info & cpu_to_le16(0x1 << bit_offset)) - return _SUCCESS; - else - return _FAIL; -} - -unsigned char get_highest_rate_idx23a(u32 mask) -{ - int i; - unsigned char rate_idx = 0; - - for (i = 27; i >= 0; i--) { - if (mask & BIT(i)) { - rate_idx = i; - break; - } - } - return rate_idx; -} - -void Update_RA_Entry23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - rtw_hal_update_ra_mask23a(psta, 0); -} - -static void enable_rate_adaptive(struct rtw_adapter *padapter, - struct sta_info *psta) -{ - Update_RA_Entry23a(padapter, psta); -} - -void set_sta_rate23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - /* rate adaptive */ - enable_rate_adaptive(padapter, psta); -} - -/* Update RRSR and Rate for USERATE */ -void update_tx_basic_rate23a(struct rtw_adapter *padapter, u8 wirelessmode) -{ - unsigned char supported_rates[NDIS_802_11_LENGTH_RATES_EX]; - - memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX); - - if (wirelessmode == WIRELESS_11B) { - memcpy(supported_rates, rtw_basic_rate_cck, 4); - } else if (wirelessmode & WIRELESS_11B) { - memcpy(supported_rates, rtw_basic_rate_mix, 7); - } else { - memcpy(supported_rates, rtw_basic_rate_ofdm, 3); - } - - if (wirelessmode & WIRELESS_11B) - update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB); - else - update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB); - - HalSetBrateCfg23a(padapter, supported_rates); -} - -unsigned char check_assoc_AP23a(u8 *pframe, uint len) -{ - int i; - u8 epigram_vendor_flag; - u8 ralink_vendor_flag; - const u8 *p; - - epigram_vendor_flag = 0; - ralink_vendor_flag = 0; - - for (i = 0; i < len;) { - p = pframe + i; - - switch (p[0]) { - case WLAN_EID_VENDOR_SPECIFIC: - if (!memcmp(p + 2, ARTHEROS_OUI1, 3) || - !memcmp(p + 2, ARTHEROS_OUI2, 3)) { - DBG_8723A("link to Artheros AP\n"); - return HT_IOT_PEER_ATHEROS; - } else if (!memcmp(p + 2, BROADCOM_OUI1, 3) || - !memcmp(p + 2, BROADCOM_OUI2, 3)) { - DBG_8723A("link to Broadcom AP\n"); - return HT_IOT_PEER_BROADCOM; - } else if (!memcmp(p + 2, MARVELL_OUI, 3)) { - DBG_8723A("link to Marvell AP\n"); - return HT_IOT_PEER_MARVELL; - } else if (!memcmp(p + 2, RALINK_OUI, 3)) { - if (!ralink_vendor_flag) - ralink_vendor_flag = 1; - else { - DBG_8723A("link to Ralink AP\n"); - return HT_IOT_PEER_RALINK; - } - } else if (!memcmp(p + 2, CISCO_OUI, 3)) { - DBG_8723A("link to Cisco AP\n"); - return HT_IOT_PEER_CISCO; - } else if (!memcmp(p + 2, REALTEK_OUI, 3)) { - DBG_8723A("link to Realtek 96B\n"); - return HT_IOT_PEER_REALTEK; - } else if (!memcmp(p + 2, AIRGOCAP_OUI, 3)) { - DBG_8723A("link to Airgo Cap\n"); - return HT_IOT_PEER_AIRGO; - } else if (!memcmp(p + 2, EPIGRAM_OUI, 3)) { - epigram_vendor_flag = 1; - if (ralink_vendor_flag) { - DBG_8723A("link to Tenda W311R AP\n"); - return HT_IOT_PEER_TENDA; - } else - DBG_8723A("Capture EPIGRAM_OUI\n"); - } else - break; - default: - break; - } - - i += (p[1] + 2); - } - - if (ralink_vendor_flag && !epigram_vendor_flag) { - DBG_8723A("link to Ralink AP\n"); - return HT_IOT_PEER_RALINK; - } else if (ralink_vendor_flag && epigram_vendor_flag) { - DBG_8723A("link to Tenda W311R AP\n"); - return HT_IOT_PEER_TENDA; - } else { - DBG_8723A("link to new AP\n"); - return HT_IOT_PEER_UNKNOWN; - } -} - -void update_IOT_info23a(struct rtw_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - switch (pmlmeinfo->assoc_AP_vendor) { - case HT_IOT_PEER_MARVELL: - pmlmeinfo->turboMode_cts2self = 1; - pmlmeinfo->turboMode_rtsen = 0; - break; - case HT_IOT_PEER_RALINK: - pmlmeinfo->turboMode_cts2self = 0; - pmlmeinfo->turboMode_rtsen = 1; - /* disable high power */ - rtl8723a_odm_support_ability_clr(padapter, (u32) - ~DYNAMIC_BB_DYNAMIC_TXPWR); - break; - case HT_IOT_PEER_REALTEK: - /* rtw_write16(padapter, 0x4cc, 0xffff); */ - /* rtw_write16(padapter, 0x546, 0x01c0); */ - /* disable high power */ - rtl8723a_odm_support_ability_clr(padapter, (u32) - ~DYNAMIC_BB_DYNAMIC_TXPWR); - break; - default: - pmlmeinfo->turboMode_cts2self = 0; - pmlmeinfo->turboMode_rtsen = 1; - break; - } -} - -void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap) -{ - struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (updateCap & cShortPreamble) { - /* Short Preamble */ - if (pmlmeinfo->preamble_mode != PREAMBLE_SHORT) { - /* PREAMBLE_LONG or PREAMBLE_AUTO */ - pmlmeinfo->preamble_mode = PREAMBLE_SHORT; - rtl8723a_ack_preamble(Adapter, true); - } - } else { /* Long Preamble */ - if (pmlmeinfo->preamble_mode != PREAMBLE_LONG) { - /* PREAMBLE_SHORT or PREAMBLE_AUTO */ - pmlmeinfo->preamble_mode = PREAMBLE_LONG; - rtl8723a_ack_preamble(Adapter, false); - } - } - if (updateCap & cIBSS) { - /* Filen: See 802.11-2007 p.91 */ - pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME; - } else { - /* Filen: See 802.11-2007 p.90 */ - if (pmlmeext->cur_wireless_mode & - (WIRELESS_11G | WIRELESS_11_24N)) { - if (updateCap & cShortSlotTime) { /* Short Slot Time */ - if (pmlmeinfo->slotTime != SHORT_SLOT_TIME) - pmlmeinfo->slotTime = SHORT_SLOT_TIME; - } else { /* Long Slot Time */ - if (pmlmeinfo->slotTime != NON_SHORT_SLOT_TIME) - pmlmeinfo->slotTime = - NON_SHORT_SLOT_TIME; - } - } else if (pmlmeext->cur_wireless_mode & - (WIRELESS_11A | WIRELESS_11_5N)) { - pmlmeinfo->slotTime = SHORT_SLOT_TIME; - } else { - /* B Mode */ - pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME; - } - } - rtl8723a_set_slot_time(Adapter, pmlmeinfo->slotTime); -} - -void update_wireless_mode23a(struct rtw_adapter *padapter) -{ - int ratelen, network_type = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct wlan_bssid_ex *cur_network = &pmlmeinfo->network; - unsigned char *rate = cur_network->SupportedRates; - - ratelen = rtw_get_rateset_len23a(cur_network->SupportedRates); - - if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) - pmlmeinfo->HT_enable = 1; - - if (pmlmeext->cur_channel > 14) { - if (pmlmeinfo->HT_enable) - network_type = WIRELESS_11_5N; - network_type |= WIRELESS_11A; - } else { - if (pmlmeinfo->HT_enable) - network_type = WIRELESS_11_24N; - - if (cckratesonly_included23a(rate, ratelen) == true) - network_type |= WIRELESS_11B; - else if (cckrates_included23a(rate, ratelen) == true) - network_type |= WIRELESS_11BG; - else - network_type |= WIRELESS_11G; - } - - pmlmeext->cur_wireless_mode = - network_type & padapter->registrypriv.wireless_mode; - - /* 0x0808 -> for CCK, 0x0a0a -> for OFDM */ - /* change this value if having IOT issues. */ - rtl8723a_set_resp_sifs(padapter, 0x08, 0x08, 0x0a, 0x0a); - - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) - update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB); - else - update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB); -} - -void update_bmc_sta_support_rate23a(struct rtw_adapter *padapter, u32 mac_id) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pmlmeext->cur_wireless_mode & WIRELESS_11B) { - /* Only B, B/G, and B/G/N AP could use CCK rate */ - memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), - rtw_basic_rate_cck, 4); - } else { - memcpy(pmlmeinfo->FW_sta_info[mac_id].SupportedRates, - rtw_basic_rate_ofdm, 3); - } -} - -int update_sta_support_rate23a(struct rtw_adapter *padapter, u8 *pvar_ie, - uint var_ie_len, int cam_idx) -{ - int supportRateNum = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - const u8 *p; - - p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pvar_ie, var_ie_len); - if (!p) - return _FAIL; - - memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, p + 2, p[1]); - supportRateNum = p[1]; - - p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pvar_ie, var_ie_len); - if (p) - memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + - supportRateNum, p + 2, p[1]); - return _SUCCESS; -} - -void process_addba_req23a(struct rtw_adapter *padapter, - u8 *paddba_req, u8 *addr) -{ - struct sta_info *psta; - u16 tid, start_seq, param; - struct recv_reorder_ctrl *preorder_ctrl; - struct sta_priv *pstapriv = &padapter->stapriv; - struct ADDBA_request *preq = (struct ADDBA_request *)paddba_req; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - psta = rtw_get_stainfo23a(pstapriv, addr); - - if (psta) { - start_seq = le16_to_cpu(preq->BA_starting_seqctrl) >> 4; - - param = le16_to_cpu(preq->BA_para_set); - tid = (param >> 2) & 0x0f; - - preorder_ctrl = &psta->recvreorder_ctrl[tid]; - - preorder_ctrl->indicate_seq = 0xffff; - - preorder_ctrl->enable = (pmlmeinfo->bAcceptAddbaReq == true) ? - true : false; - } -} diff --git a/drivers/staging/rtl8723au/core/rtw_xmit.c b/drivers/staging/rtl8723au/core/rtw_xmit.c deleted file mode 100644 index 3de40cfa5f3b..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_xmit.c +++ /dev/null @@ -1,2341 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_XMIT_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <wifi.h> -#include <osdep_intf.h> -#include <linux/ip.h> -#include <usb_ops.h> -#include <rtl8723a_xmit.h> - -static void _init_txservq(struct tx_servq *ptxservq) -{ - - INIT_LIST_HEAD(&ptxservq->tx_pending); - _rtw_init_queue23a(&ptxservq->sta_pending); - ptxservq->qcnt = 0; - -} - -void _rtw_init_sta_xmit_priv23a(struct sta_xmit_priv *psta_xmitpriv) -{ - - spin_lock_init(&psta_xmitpriv->lock); - - /* for (i = 0 ; i < MAX_NUMBLKS; i++) */ - /* _init_txservq(&psta_xmitpriv->blk_q[i]); */ - - _init_txservq(&psta_xmitpriv->be_q); - _init_txservq(&psta_xmitpriv->bk_q); - _init_txservq(&psta_xmitpriv->vi_q); - _init_txservq(&psta_xmitpriv->vo_q); - INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz); - INIT_LIST_HEAD(&psta_xmitpriv->apsd); - -} - -int _rtw_init_xmit_priv23a(struct xmit_priv *pxmitpriv, - struct rtw_adapter *padapter) -{ - int i; - struct xmit_buf *pxmitbuf; - struct xmit_frame *pxframe; - int res = _SUCCESS; - u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ; - u32 num_xmit_extbuf = NR_XMIT_EXTBUFF; - - spin_lock_init(&pxmitpriv->lock); - spin_lock_init(&pxmitpriv->lock_sctx); - sema_init(&pxmitpriv->xmit_sema, 0); - sema_init(&pxmitpriv->terminate_xmitthread_sema, 0); - - pxmitpriv->adapter = padapter; - - _rtw_init_queue23a(&pxmitpriv->be_pending); - _rtw_init_queue23a(&pxmitpriv->bk_pending); - _rtw_init_queue23a(&pxmitpriv->vi_pending); - _rtw_init_queue23a(&pxmitpriv->vo_pending); - _rtw_init_queue23a(&pxmitpriv->bm_pending); - - _rtw_init_queue23a(&pxmitpriv->free_xmit_queue); - - for (i = 0; i < NR_XMITFRAME; i++) { - pxframe = kzalloc(sizeof(struct xmit_frame), GFP_KERNEL); - if (!pxframe) - break; - INIT_LIST_HEAD(&pxframe->list); - - pxframe->padapter = padapter; - pxframe->frame_tag = NULL_FRAMETAG; - - list_add_tail(&pxframe->list, - &pxmitpriv->free_xmit_queue.queue); - } - - pxmitpriv->free_xmitframe_cnt = i; - - pxmitpriv->frag_len = MAX_FRAG_THRESHOLD; - - /* init xmit_buf */ - _rtw_init_queue23a(&pxmitpriv->free_xmitbuf_queue); - INIT_LIST_HEAD(&pxmitpriv->xmitbuf_list); - _rtw_init_queue23a(&pxmitpriv->pending_xmitbuf_queue); - - for (i = 0; i < NR_XMITBUFF; i++) { - pxmitbuf = kzalloc(sizeof(struct xmit_buf), GFP_KERNEL); - if (!pxmitbuf) - goto fail; - INIT_LIST_HEAD(&pxmitbuf->list); - INIT_LIST_HEAD(&pxmitbuf->list2); - - pxmitbuf->padapter = padapter; - - /* Tx buf allocation may fail sometimes, so sleep and retry. */ - res = rtw_os_xmit_resource_alloc23a(padapter, pxmitbuf, - (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); - if (res == _FAIL) { - goto fail; - } - - list_add_tail(&pxmitbuf->list, - &pxmitpriv->free_xmitbuf_queue.queue); - list_add_tail(&pxmitbuf->list2, - &pxmitpriv->xmitbuf_list); - } - - pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF; - - /* init xframe_ext queue, the same count as extbuf */ - _rtw_init_queue23a(&pxmitpriv->free_xframe_ext_queue); - - for (i = 0; i < num_xmit_extbuf; i++) { - pxframe = kzalloc(sizeof(struct xmit_frame), GFP_KERNEL); - if (!pxframe) - break; - INIT_LIST_HEAD(&pxframe->list); - - pxframe->padapter = padapter; - pxframe->frame_tag = NULL_FRAMETAG; - - pxframe->pkt = NULL; - - pxframe->buf_addr = NULL; - pxframe->pxmitbuf = NULL; - - pxframe->ext_tag = 1; - - list_add_tail(&pxframe->list, - &pxmitpriv->free_xframe_ext_queue.queue); - } - pxmitpriv->free_xframe_ext_cnt = i; - - /* Init xmit extension buff */ - _rtw_init_queue23a(&pxmitpriv->free_xmit_extbuf_queue); - INIT_LIST_HEAD(&pxmitpriv->xmitextbuf_list); - - for (i = 0; i < num_xmit_extbuf; i++) { - pxmitbuf = kzalloc(sizeof(struct xmit_buf), GFP_KERNEL); - if (!pxmitbuf) - goto fail; - INIT_LIST_HEAD(&pxmitbuf->list); - INIT_LIST_HEAD(&pxmitbuf->list2); - - pxmitbuf->padapter = padapter; - - /* Tx buf allocation may fail sometimes, so sleep and retry. */ - res = rtw_os_xmit_resource_alloc23a(padapter, pxmitbuf, - max_xmit_extbuf_size + XMITBUF_ALIGN_SZ); - if (res == _FAIL) { - goto exit; - } - - list_add_tail(&pxmitbuf->list, - &pxmitpriv->free_xmit_extbuf_queue.queue); - list_add_tail(&pxmitbuf->list2, - &pxmitpriv->xmitextbuf_list); - } - - pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf; - - rtw_alloc_hwxmits23a(padapter); - rtw_init_hwxmits23a(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); - - for (i = 0; i < 4; i ++) - pxmitpriv->wmm_para_seq[i] = i; - - sema_init(&pxmitpriv->tx_retevt, 0); - - pxmitpriv->ack_tx = false; - mutex_init(&pxmitpriv->ack_tx_mutex); - rtw_sctx_init23a(&pxmitpriv->ack_tx_ops, 0); - tasklet_init(&padapter->xmitpriv.xmit_tasklet, - (void(*)(unsigned long))rtl8723au_xmit_tasklet, - (unsigned long)padapter); - -exit: - - return res; -fail: - goto exit; -} - -void _rtw_free_xmit_priv23a(struct xmit_priv *pxmitpriv) -{ - struct rtw_adapter *padapter = pxmitpriv->adapter; - struct xmit_frame *pxframe, *ptmp; - struct xmit_buf *pxmitbuf, *ptmp2; - - list_for_each_entry_safe(pxframe, ptmp, - &pxmitpriv->free_xmit_queue.queue, list) { - list_del_init(&pxframe->list); - rtw_os_xmit_complete23a(padapter, pxframe); - kfree(pxframe); - } - - list_for_each_entry_safe(pxmitbuf, ptmp2, - &pxmitpriv->xmitbuf_list, list2) { - list_del_init(&pxmitbuf->list2); - rtw_os_xmit_resource_free23a(padapter, pxmitbuf); - kfree(pxmitbuf); - } - - /* free xframe_ext queue, the same count as extbuf */ - list_for_each_entry_safe(pxframe, ptmp, - &pxmitpriv->free_xframe_ext_queue.queue, - list) { - list_del_init(&pxframe->list); - rtw_os_xmit_complete23a(padapter, pxframe); - kfree(pxframe); - } - - /* free xmit extension buff */ - list_for_each_entry_safe(pxmitbuf, ptmp2, - &pxmitpriv->xmitextbuf_list, list2) { - list_del_init(&pxmitbuf->list2); - rtw_os_xmit_resource_free23a(padapter, pxmitbuf); - kfree(pxmitbuf); - } - - rtw_free_hwxmits23a(padapter); - mutex_destroy(&pxmitpriv->ack_tx_mutex); -} - -static void update_attrib_vcs_info(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe) -{ - u32 sz; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct sta_info *psta = pattrib->psta; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state); - return; - } - - if (pattrib->nr_frags != 1) - sz = padapter->xmitpriv.frag_len; - else /* no frag */ - sz = pattrib->last_txcmdsz; - - /* (1) RTS_Threshold is compared to the MPDU, not MSDU. */ - /* (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. */ - /* Other fragments are protected by previous fragment. */ - /* So we only need to check the length of first fragment. */ - if (pmlmeext->cur_wireless_mode < WIRELESS_11_24N || padapter->registrypriv.wifi_spec) { - if (sz > padapter->registrypriv.rts_thresh) { - pattrib->vcs_mode = RTS_CTS; - } else { - if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - else - pattrib->vcs_mode = NONE_VCS; - } - } else { - while (true) { - /* IOT action */ - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS && - pattrib->ampdu_en && - padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) { - pattrib->vcs_mode = CTS_TO_SELF; - break; - } - - /* check ERP protection */ - if (psta->rtsen || psta->cts2self) { - if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - - break; - } - - /* check HT op mode */ - if (pattrib->ht_en) { - u8 HTOpMode = pmlmeinfo->HT_protection; - - if ((pmlmeext->cur_bwmode && (HTOpMode == 2 || HTOpMode == 3)) || - (!pmlmeext->cur_bwmode && HTOpMode == 3)) { - pattrib->vcs_mode = RTS_CTS; - break; - } - } - - /* check rts */ - if (sz > padapter->registrypriv.rts_thresh) { - pattrib->vcs_mode = RTS_CTS; - break; - } - - /* to do list: check MIMO power save condition. */ - - /* check AMPDU aggregation for TXOP */ - if (pattrib->ampdu_en) { - pattrib->vcs_mode = RTS_CTS; - break; - } - - pattrib->vcs_mode = NONE_VCS; - break; - } - } -} - -static void update_attrib_phy_info(struct pkt_attrib *pattrib, struct sta_info *psta) -{ - /*if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - else - pattrib->vcs_mode = NONE_VCS;*/ - - pattrib->mdata = 0; - pattrib->eosp = 0; - pattrib->triggered = 0; - - /* qos_en, ht_en, init rate, , bw, ch_offset, sgi */ - pattrib->qos_en = psta->qos_option; - - pattrib->raid = psta->raid; - pattrib->ht_en = psta->htpriv.ht_option; - pattrib->bwmode = psta->htpriv.bwmode; - pattrib->ch_offset = psta->htpriv.ch_offset; - pattrib->sgi = psta->htpriv.sgi; - pattrib->ampdu_en = false; - - pattrib->retry_ctrl = false; -} - -u8 qos_acm23a(u8 acm_mask, u8 priority) -{ - u8 change_priority = priority; - - switch (priority) { - case 0: - case 3: - if (acm_mask & BIT(1)) - change_priority = 1; - break; - case 1: - case 2: - break; - case 4: - case 5: - if (acm_mask & BIT(2)) - change_priority = 0; - break; - case 6: - case 7: - if (acm_mask & BIT(3)) - change_priority = 5; - break; - default: - DBG_8723A("qos_acm23a(): invalid pattrib->priority: %d!!!\n", - priority); - change_priority = 0; - break; - } - - return change_priority; -} - -static void set_qos(struct sk_buff *skb, struct pkt_attrib *pattrib) -{ - u8 *pframe = skb->data; - struct iphdr *ip_hdr; - u8 UserPriority = 0; - - /* get UserPriority from IP hdr */ - if (pattrib->ether_type == ETH_P_IP) { - ip_hdr = (struct iphdr *)(pframe + ETH_HLEN); - UserPriority = ip_hdr->tos >> 5; - } else if (pattrib->ether_type == ETH_P_PAE) { - /* "When priority processing of data frames is supported, */ - /* a STA's SME should send EAPOL-Key frames at the highest - priority." */ - UserPriority = 7; - } - - pattrib->priority = UserPriority; - pattrib->hdrlen = sizeof(struct ieee80211_qos_hdr); - pattrib->type = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA; -} - -static int update_attrib(struct rtw_adapter *padapter, - struct sk_buff *skb, struct pkt_attrib *pattrib) -{ - struct sta_info *psta = NULL; - int bmcast; - struct sta_priv *pstapriv = &padapter->stapriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int res = _SUCCESS; - struct ethhdr *ehdr = (struct ethhdr *) skb->data; - - pattrib->ether_type = ntohs(ehdr->h_proto); - - ether_addr_copy(pattrib->dst, ehdr->h_dest); - ether_addr_copy(pattrib->src, ehdr->h_source); - - pattrib->pctrl = 0; - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - ether_addr_copy(pattrib->ra, pattrib->dst); - ether_addr_copy(pattrib->ta, pattrib->src); - } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - ether_addr_copy(pattrib->ra, get_bssid(pmlmepriv)); - ether_addr_copy(pattrib->ta, pattrib->src); - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - ether_addr_copy(pattrib->ra, pattrib->dst); - ether_addr_copy(pattrib->ta, get_bssid(pmlmepriv)); - } - - pattrib->pktlen = skb->len - ETH_HLEN; - - if (pattrib->ether_type == ETH_P_IP) { - /* The following is for DHCP and ARP packet, we use cck1M - to tx these packets and let LPS awake some time */ - /* to prevent DHCP protocol fail */ - pattrib->dhcp_pkt = 0; - /* MINIMUM_DHCP_PACKET_SIZE) { */ - if (pattrib->pktlen > 282 + 24) { - if (pattrib->ether_type == ETH_P_IP) {/* IP header */ - u8 *pframe = skb->data; - - pframe += ETH_HLEN; - - if ((pframe[21] == 68 && pframe[23] == 67) || - (pframe[21] == 67 && pframe[23] == 68)) { - /* 68 : UDP BOOTP client */ - /* 67 : UDP BOOTP server */ - RT_TRACE(_module_rtl871x_xmit_c_, - _drv_err_, - "======================update_attrib: get DHCP Packet\n"); - pattrib->dhcp_pkt = 1; - } - } - } - } else if (pattrib->ether_type == ETH_P_PAE) { - DBG_8723A_LEVEL(_drv_always_, "send eapol packet\n"); - } - - if ((pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) { - rtw_set_scan_deny(padapter, 3000); - } - - /* If EAPOL , ARP , OR DHCP packet, driver must be in active mode. */ - if ((pattrib->ether_type == ETH_P_ARP) || - (pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) { - rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SPECIAL_PACKET, 1); - } - - bmcast = is_multicast_ether_addr(pattrib->ra); - - /* get sta_info */ - if (bmcast) { - psta = rtw_get_bcmc_stainfo23a(padapter); - } else { - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - if (psta == NULL) { /* if we cannot get psta => drrp the pkt */ - RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, - "update_attrib => get sta_info fail, ra:%pM\n", - pattrib->ra); - res = _FAIL; - goto exit; - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) && - (!(psta->state & _FW_LINKED))) { - res = _FAIL; - goto exit; - } - } - - if (psta) { - pattrib->mac_id = psta->mac_id; - /* DBG_8723A("%s ==> mac_id(%d)\n", __func__, pattrib->mac_id); */ - pattrib->psta = psta; - } else { - /* if we cannot get psta => drop the pkt */ - RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, - "update_attrib => get sta_info fail, ra:%pM\n", - pattrib->ra); - res = _FAIL; - goto exit; - } - - pattrib->ack_policy = 0; - /* get ether_hdr_len */ - - /* pattrib->ether_type == 0x8100) ? (14 + 4): 14; vlan tag */ - pattrib->pkt_hdrlen = ETH_HLEN; - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - pattrib->type = IEEE80211_FTYPE_DATA; - pattrib->priority = 0; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE | WIFI_ADHOC_STATE | - WIFI_ADHOC_MASTER_STATE)) { - if (psta->qos_option) - set_qos(skb, pattrib); - } else { - if (pmlmepriv->qos_option) { - set_qos(skb, pattrib); - - if (pmlmepriv->acm_mask != 0) { - pattrib->priority = qos_acm23a(pmlmepriv->acm_mask, - pattrib->priority); - } - } - } - - if (psta->ieee8021x_blocked == true) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "psta->ieee8021x_blocked == true\n"); - - pattrib->encrypt = 0; - - if ((pattrib->ether_type != ETH_P_PAE) && - !check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "psta->ieee8021x_blocked == true, pattrib->ether_type(%.4x) != 0x888e\n", - pattrib->ether_type); - res = _FAIL; - goto exit; - } - } else { - GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast); - - switch (psecuritypriv->dot11AuthAlgrthm) { - case dot11AuthAlgrthm_Open: - case dot11AuthAlgrthm_Shared: - case dot11AuthAlgrthm_Auto: - pattrib->key_idx = - (u8)psecuritypriv->dot11PrivacyKeyIndex; - break; - case dot11AuthAlgrthm_8021X: - if (bmcast) - pattrib->key_idx = - (u8)psecuritypriv->dot118021XGrpKeyid; - else - pattrib->key_idx = 0; - break; - default: - pattrib->key_idx = 0; - break; - } - - } - - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - pattrib->iv_len = IEEE80211_WEP_IV_LEN; - pattrib->icv_len = IEEE80211_WEP_ICV_LEN; - break; - - case WLAN_CIPHER_SUITE_TKIP: - pattrib->iv_len = IEEE80211_TKIP_IV_LEN; - pattrib->icv_len = IEEE80211_TKIP_ICV_LEN; - - if (!padapter->securitypriv.busetkipkey) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "padapter->securitypriv.busetkipkey(%d) == false drop packet\n", - padapter->securitypriv.busetkipkey); - res = _FAIL; - goto exit; - } - - break; - case WLAN_CIPHER_SUITE_CCMP: - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "pattrib->encrypt =%d (WLAN_CIPHER_SUITE_CCMP)\n", - pattrib->encrypt); - pattrib->iv_len = IEEE80211_CCMP_HDR_LEN; - pattrib->icv_len = IEEE80211_CCMP_MIC_LEN; - break; - - default: - pattrib->iv_len = 0; - pattrib->icv_len = 0; - break; - } - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "update_attrib: encrypt =%d\n", pattrib->encrypt); - - if (pattrib->encrypt && !psecuritypriv->hw_decrypted) { - pattrib->bswenc = true; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "update_attrib: encrypt =%d bswenc = true\n", - pattrib->encrypt); - } else { - pattrib->bswenc = false; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "update_attrib: bswenc = false\n"); - } - update_attrib_phy_info(pattrib, psta); - -exit: - - return res; -} - -static int xmitframe_addmic(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) { - struct mic_data micdata; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int curfragnum, length; - u8 *pframe, *payload, mic[8]; - u8 priority[4]= {0x0, 0x0, 0x0, 0x0}; - u8 hw_hdr_offset = 0; - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (pattrib->psta) { - stainfo = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - stainfo = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - - if (!stainfo) { - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - if (!(stainfo->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", - __func__, stainfo->state); - return _FAIL; - } - - hw_hdr_offset = TXDESC_OFFSET; - - if (pattrib->encrypt == WLAN_CIPHER_SUITE_TKIP) { - /* encode mic code */ - if (stainfo) { - u8 null_key[16]={0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0}; - - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - if (bmcst) { - if (!memcmp(psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey, null_key, 16)) { - return _FAIL; - } - /* start to calculate the mic code */ - rtw_secmicsetkey23a(&micdata, psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey); - } else { - if (!memcmp(&stainfo->dot11tkiptxmickey.skey[0], - null_key, 16)) { - return _FAIL; - } - /* start to calculate the mic code */ - rtw_secmicsetkey23a(&micdata, &stainfo->dot11tkiptxmickey.skey[0]); - } - - if (pframe[1] & 1) { /* ToDS == 1 */ - /* DA */ - rtw_secmicappend23a(&micdata, &pframe[16], 6); - if (pframe[1] & 2) /* From Ds == 1 */ - rtw_secmicappend23a(&micdata, - &pframe[24], 6); - else - rtw_secmicappend23a(&micdata, - &pframe[10], 6); - } else { /* ToDS == 0 */ - /* DA */ - rtw_secmicappend23a(&micdata, &pframe[4], 6); - if (pframe[1] & 2) /* From Ds == 1 */ - rtw_secmicappend23a(&micdata, - &pframe[16], 6); - else - rtw_secmicappend23a(&micdata, - &pframe[10], 6); - } - - /* if (pmlmepriv->qos_option == 1) */ - if (pattrib->qos_en) - priority[0] = (u8)pxmitframe->attrib.priority; - - rtw_secmicappend23a(&micdata, &priority[0], 4); - - payload = pframe; - - for (curfragnum = 0; curfragnum < pattrib->nr_frags; - curfragnum++) { - payload = PTR_ALIGN(payload, 4); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "=== curfragnum =%d, pframe = 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x,!!!\n", - curfragnum, *payload, *(payload + 1), - *(payload + 2), *(payload + 3), - *(payload + 4), *(payload + 5), - *(payload + 6), *(payload + 7)); - - payload = payload + pattrib->hdrlen + - pattrib->iv_len; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "curfragnum =%d pattrib->hdrlen =%d pattrib->iv_len =%d\n", - curfragnum, - pattrib->hdrlen, pattrib->iv_len); - if ((curfragnum + 1) == pattrib->nr_frags) { - length = pattrib->last_txcmdsz - - pattrib->hdrlen - - pattrib->iv_len - - ((pattrib->bswenc) ? - pattrib->icv_len : 0); - rtw_secmicappend23a(&micdata, payload, - length); - payload = payload + length; - } else { - length = pxmitpriv->frag_len - - pattrib->hdrlen - - pattrib->iv_len - - ((pattrib->bswenc) ? - pattrib->icv_len : 0); - rtw_secmicappend23a(&micdata, payload, - length); - payload = payload + length + - pattrib->icv_len; - RT_TRACE(_module_rtl871x_xmit_c_, - _drv_err_, - "curfragnum =%d length =%d pattrib->icv_len =%d\n", - curfragnum, length, - pattrib->icv_len); - } - } - rtw_secgetmic23a(&micdata, &mic[0]); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: before add mic code!!\n"); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: pattrib->last_txcmdsz =%d!!!\n", - pattrib->last_txcmdsz); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: mic[0]= 0x%.2x , mic[1]=0x%.2x , mic[2]= 0x%.2x , mic[3]= 0x%.2x\nmic[4]= 0x%.2x , mic[5]= 0x%.2x , mic[6]= 0x%.2x , mic[7]= 0x%.2x !!!!\n", - mic[0], mic[1], mic[2], mic[3], - mic[4], mic[5], mic[6], mic[7]); - /* add mic code and add the mic code length - in last_txcmdsz */ - - memcpy(payload, &mic[0], 8); - pattrib->last_txcmdsz += 8; - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "======== last pkt ========\n"); - payload = payload - pattrib->last_txcmdsz + 8; - for (curfragnum = 0; curfragnum < pattrib->last_txcmdsz; - curfragnum = curfragnum + 8) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "%.2x, %.2x, %.2x, %.2x, %.2x, %.2x, %.2x, %.2x\n", - *(payload + curfragnum), - *(payload + curfragnum + 1), - *(payload + curfragnum + 2), - *(payload + curfragnum + 3), - *(payload + curfragnum + 4), - *(payload + curfragnum + 5), - *(payload + curfragnum + 6), - *(payload + curfragnum + 7)); - } - } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: rtw_get_stainfo23a ==NULL!!!\n"); - } - } - - return _SUCCESS; -} - -static int xmitframe_swencrypt(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - /* if ((psecuritypriv->sw_encrypt)||(pattrib->bswenc)) */ - if (pattrib->bswenc) { - /* DBG_8723A("start xmitframe_swencrypt\n"); */ - RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, - "### xmitframe_swencrypt\n"); - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - rtw_wep_encrypt23a(padapter, pxmitframe); - break; - case WLAN_CIPHER_SUITE_TKIP: - rtw_tkip_encrypt23a(padapter, pxmitframe); - break; - case WLAN_CIPHER_SUITE_CCMP: - rtw_aes_encrypt23a(padapter, pxmitframe); - break; - default: - break; - } - - } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_, - "### xmitframe_hwencrypt\n"); - } - - return _SUCCESS; -} - -static int rtw_make_wlanhdr(struct rtw_adapter *padapter, u8 *hdr, - struct pkt_attrib *pattrib) -{ - struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr; - struct ieee80211_qos_hdr *qoshdr; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 qos_option = false; - int res = _SUCCESS; - - struct sta_info *psta; - - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - if (bmcst) { - psta = rtw_get_bcmc_stainfo23a(padapter); - } else { - psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra); - } - } - - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state); - return _FAIL; - } - - memset(hdr, 0, WLANHDR_OFFSET); - - pwlanhdr->frame_control = cpu_to_le16(pattrib->type); - - if (pattrib->type & IEEE80211_FTYPE_DATA) { - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - /* to_ds = 1, fr_ds = 0; */ - /* Data transfer to AP */ - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_TODS); - ether_addr_copy(pwlanhdr->addr1, get_bssid(pmlmepriv)); - ether_addr_copy(pwlanhdr->addr2, pattrib->src); - ether_addr_copy(pwlanhdr->addr3, pattrib->dst); - - if (pmlmepriv->qos_option) - qos_option = true; - - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* to_ds = 0, fr_ds = 1; */ - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_FROMDS); - ether_addr_copy(pwlanhdr->addr1, pattrib->dst); - ether_addr_copy(pwlanhdr->addr2, get_bssid(pmlmepriv)); - ether_addr_copy(pwlanhdr->addr3, pattrib->src); - - if (psta->qos_option) - qos_option = true; - } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - ether_addr_copy(pwlanhdr->addr1, pattrib->dst); - ether_addr_copy(pwlanhdr->addr2, pattrib->src); - ether_addr_copy(pwlanhdr->addr3, get_bssid(pmlmepriv)); - - if (psta->qos_option) - qos_option = true; - } - else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "fw_state:%x is not allowed to xmit frame\n", - get_fwstate(pmlmepriv)); - res = _FAIL; - goto exit; - } - if (pattrib->mdata) - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_MOREDATA); - if (pattrib->encrypt) - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_PROTECTED); - if (qos_option) { - qoshdr = (struct ieee80211_qos_hdr *)hdr; - - qoshdr->qos_ctrl = cpu_to_le16( - pattrib->priority & IEEE80211_QOS_CTL_TID_MASK); - - qoshdr->qos_ctrl |= cpu_to_le16( - (pattrib->ack_policy << 5) & - IEEE80211_QOS_CTL_ACK_POLICY_MASK); - - if (pattrib->eosp) - qoshdr->qos_ctrl |= - cpu_to_le16(IEEE80211_QOS_CTL_EOSP); - } - /* TODO: fill HT Control Field */ - - /* Update Seq Num will be handled by f/w */ - if (psta) { - psta->sta_xmitpriv.txseq_tid[pattrib->priority]++; - psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF; - pattrib->seqnum = psta->sta_xmitpriv.txseq_tid[pattrib->priority]; - /* We dont need to worry about frag bits here */ - pwlanhdr->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ( - pattrib->seqnum)); - /* check if enable ampdu */ - if (pattrib->ht_en && psta->htpriv.ampdu_enable) { - if (pattrib->priority >= 16) - printk(KERN_WARNING "%s: Invalid " - "pattrib->priority %i\n", - __func__, pattrib->priority); - if (psta->htpriv.agg_enable_bitmap & - BIT(pattrib->priority)) - pattrib->ampdu_en = true; - } - /* re-check if enable ampdu by BA_starting_seqctrl */ - if (pattrib->ampdu_en) { - u16 tx_seq; - - tx_seq = psta->BA_starting_seqctrl[pattrib->priority & 0x0f]; - - /* check BA_starting_seqctrl */ - if (SN_LESS(pattrib->seqnum, tx_seq)) { - /* DBG_8723A("tx ampdu seqnum(%d) < tx_seq(%d)\n", pattrib->seqnum, tx_seq); */ - pattrib->ampdu_en = false;/* AGG BK */ - } else if (SN_EQUAL(pattrib->seqnum, tx_seq)) { - psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (tx_seq+1)&0xfff; - pattrib->ampdu_en = true;/* AGG EN */ - } else { - /* DBG_8723A("tx ampdu over run\n"); */ - psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (pattrib->seqnum+1)&0xfff; - pattrib->ampdu_en = true;/* AGG EN */ - } - } - } - } -exit: - return res; -} - -s32 rtw_txframes_pending23a(struct rtw_adapter *padapter) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - return (!list_empty(&pxmitpriv->be_pending.queue)) || - (!list_empty(&pxmitpriv->bk_pending.queue)) || - (!list_empty(&pxmitpriv->vi_pending.queue)) || - (!list_empty(&pxmitpriv->vo_pending.queue)); -} - -s32 rtw_txframes_sta_ac_pending23a(struct rtw_adapter *padapter, - struct pkt_attrib *pattrib) -{ - struct sta_info *psta; - struct tx_servq *ptxservq; - int priority = pattrib->priority; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return 0; - } - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, - psta->state); - return 0; - } - switch (priority) { - case 1: - case 2: - ptxservq = &psta->sta_xmitpriv.bk_q; - break; - case 4: - case 5: - ptxservq = &psta->sta_xmitpriv.vi_q; - break; - case 6: - case 7: - ptxservq = &psta->sta_xmitpriv.vo_q; - break; - case 0: - case 3: - default: - ptxservq = &psta->sta_xmitpriv.be_q; - break; - } - return ptxservq->qcnt; -} - -/* Logical Link Control(LLC) SubNetwork Attachment Point(SNAP) header - * IEEE LLC/SNAP header contains 8 octets - * First 3 octets comprise the LLC portion - * SNAP portion, 5 octets, is divided into two fields: - * Organizationally Unique Identifier(OUI), 3 octets, - * type, defined by that organization, 2 octets. - */ -static int rtw_put_snap(u8 *data, u16 h_proto) -{ - if (h_proto == ETH_P_IPX || h_proto == ETH_P_AARP) - ether_addr_copy(data, bridge_tunnel_header); - else - ether_addr_copy(data, rfc1042_header); - - data += ETH_ALEN; - put_unaligned_be16(h_proto, data); - return ETH_ALEN + sizeof(u16); -} - -/* - -This sub-routine will perform all the following: - -1. remove 802.3 header. -2. create wlan_header, based on the info in pxmitframe -3. append sta's iv/ext-iv -4. append LLC -5. move frag chunk from pframe to pxmitframe->mem -6. apply sw-encrypt, if necessary. - -*/ -int rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *skb, - struct xmit_frame *pxmitframe) -{ - struct sta_info *psta; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct ieee80211_hdr *hdr; - s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz; - u8 *pframe, *mem_start; - u8 hw_hdr_offset; - u8 *pbuf_start; - u8 *pdata = skb->data; - int data_len = skb->len; - s32 bmcst = is_multicast_ether_addr(pattrib->ra); - int res = _SUCCESS; - - if (pattrib->psta) - psta = pattrib->psta; - else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra); - } - - if (!psta) { - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", - __func__, psta->state); - return _FAIL; - } - - if (!pxmitframe->buf_addr) { - DBG_8723A("==> %s buf_addr == NULL\n", __func__); - return _FAIL; - } - - pbuf_start = pxmitframe->buf_addr; - - hw_hdr_offset = TXDESC_OFFSET; - - mem_start = pbuf_start + hw_hdr_offset; - - if (rtw_make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "%s: rtw_make_wlanhdr fail; drop pkt\n", __func__); - res = _FAIL; - goto exit; - } - - pdata += pattrib->pkt_hdrlen; - data_len -= pattrib->pkt_hdrlen; - - frg_inx = 0; - frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */ - - while (1) { - llc_sz = 0; - - mpdu_len = frg_len; - - pframe = mem_start; - hdr = (struct ieee80211_hdr *)mem_start; - - pframe += pattrib->hdrlen; - mpdu_len -= pattrib->hdrlen; - - /* adding icv, if necessary... */ - if (pattrib->iv_len) { - if (psta) { - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - WEP_IV(pattrib->iv, psta->dot11txpn, - pattrib->key_idx); - break; - case WLAN_CIPHER_SUITE_TKIP: - if (bmcst) - TKIP_IV(pattrib->iv, - psta->dot11txpn, - pattrib->key_idx); - else - TKIP_IV(pattrib->iv, - psta->dot11txpn, 0); - break; - case WLAN_CIPHER_SUITE_CCMP: - if (bmcst) - AES_IV(pattrib->iv, - psta->dot11txpn, - pattrib->key_idx); - else - AES_IV(pattrib->iv, - psta->dot11txpn, 0); - break; - } - } - - memcpy(pframe, pattrib->iv, pattrib->iv_len); - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_, - "rtw_xmiaframe_coalesce23a: keyid =%d pattrib->iv[3]=%.2x pframe =%.2x %.2x %.2x %.2x\n", - padapter->securitypriv.dot11PrivacyKeyIndex, - pattrib->iv[3], *pframe, *(pframe+1), - *(pframe+2), *(pframe+3)); - pframe += pattrib->iv_len; - mpdu_len -= pattrib->iv_len; - } - if (frg_inx == 0) { - llc_sz = rtw_put_snap(pframe, pattrib->ether_type); - pframe += llc_sz; - mpdu_len -= llc_sz; - } - - if (pattrib->icv_len > 0 && pattrib->bswenc) - mpdu_len -= pattrib->icv_len; - - if (bmcst) - /* don't do fragment to broadcast/multicast packets */ - mem_sz = min_t(s32, data_len, pattrib->pktlen); - else - mem_sz = min_t(s32, data_len, mpdu_len); - - memcpy(pframe, pdata, mem_sz); - - pframe += mem_sz; - pdata += mem_sz; - data_len -= mem_sz; - - if ((pattrib->icv_len >0) && (pattrib->bswenc)) { - memcpy(pframe, pattrib->icv, pattrib->icv_len); - pframe += pattrib->icv_len; - } - - frg_inx++; - - if (bmcst || data_len <= 0) { - pattrib->nr_frags = frg_inx; - - pattrib->last_txcmdsz = pattrib->hdrlen + - pattrib->iv_len + - ((pattrib->nr_frags == 1) ? - llc_sz : 0) + - ((pattrib->bswenc) ? - pattrib->icv_len : 0) + mem_sz; - hdr->frame_control &= - ~cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); - - break; - } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "%s: There're still something in packet!\n", - __func__); - } - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); - - mem_start = PTR_ALIGN(pframe, 4) + hw_hdr_offset; - memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen); - } - - if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"); - DBG_8723A("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"); - res = _FAIL; - goto exit; - } - - xmitframe_swencrypt(padapter, pxmitframe); - - if (bmcst == false) - update_attrib_vcs_info(padapter, pxmitframe); - else - pattrib->vcs_mode = NONE_VCS; - -exit: - return res; -} - -void rtw_update_protection23a(struct rtw_adapter *padapter, u8 *ie, uint ie_len) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - uint protection; - const u8 *p; - - switch (pregistrypriv->vrtl_carrier_sense) { - case DISABLE_VCS: - pxmitpriv->vcs = NONE_VCS; - break; - case ENABLE_VCS: - break; - case AUTO_VCS: - default: - p = cfg80211_find_ie(WLAN_EID_ERP_INFO, ie, ie_len); - if (!p) - pxmitpriv->vcs = NONE_VCS; - else { - protection = (*(p + 2)) & BIT(1); - if (protection) { - if (pregistrypriv->vcs_type == RTS_CTS) - pxmitpriv->vcs = RTS_CTS; - else - pxmitpriv->vcs = CTS_TO_SELF; - } else { - pxmitpriv->vcs = NONE_VCS; - } - } - break; - } -} - -void rtw_count_tx_stats23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe, int sz) -{ - struct sta_info *psta = NULL; - struct stainfo_stats *pstats = NULL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pxmitframe->frame_tag == DATA_FRAMETAG) { - pxmitpriv->tx_bytes += sz; - pmlmepriv->LinkDetectInfo.NumTxOkInPeriod++; - - psta = pxmitframe->attrib.psta; - if (psta) { - pstats = &psta->sta_stats; - pstats->tx_pkts++; - pstats->tx_bytes += sz; - } - } -} - -struct xmit_buf *rtw_alloc_xmitbuf23a_ext(struct xmit_priv *pxmitpriv) -{ - unsigned long irqL; - struct xmit_buf *pxmitbuf = NULL; - struct list_head *phead; - struct rtw_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue; - - spin_lock_irqsave(&pfree_queue->lock, irqL); - - phead = get_list_head(pfree_queue); - - if (!list_empty(phead)) { - pxmitbuf = list_first_entry(phead, struct xmit_buf, list); - - list_del_init(&pxmitbuf->list); - - pxmitpriv->free_xmit_extbuf_cnt--; - pxmitbuf->priv_data = NULL; - pxmitbuf->ext_tag = true; - - if (pxmitbuf->sctx) { - DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__); - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); - } - } - - spin_unlock_irqrestore(&pfree_queue->lock, irqL); - - return pxmitbuf; -} - -int rtw_free_xmitbuf_ext23a(struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf) -{ - unsigned long irqL; - struct rtw_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue; - - if (pxmitbuf == NULL) - return _FAIL; - - spin_lock_irqsave(&pfree_queue->lock, irqL); - - list_del_init(&pxmitbuf->list); - - list_add_tail(&pxmitbuf->list, get_list_head(pfree_queue)); - pxmitpriv->free_xmit_extbuf_cnt++; - - spin_unlock_irqrestore(&pfree_queue->lock, irqL); - - return _SUCCESS; -} - -struct xmit_buf *rtw_alloc_xmitbuf23a(struct xmit_priv *pxmitpriv) -{ - unsigned long irqL; - struct xmit_buf *pxmitbuf = NULL; - struct list_head *phead; - struct rtw_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; - - /* DBG_8723A("+rtw_alloc_xmitbuf23a\n"); */ - - spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL); - - phead = get_list_head(pfree_xmitbuf_queue); - - if (!list_empty(phead)) { - pxmitbuf = list_first_entry(phead, struct xmit_buf, list); - - list_del_init(&pxmitbuf->list); - - pxmitpriv->free_xmitbuf_cnt--; - pxmitbuf->priv_data = NULL; - pxmitbuf->ext_tag = false; - pxmitbuf->flags = XMIT_VO_QUEUE; - - if (pxmitbuf->sctx) { - DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__); - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); - } - } - - spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL); - - return pxmitbuf; -} - -int rtw_free_xmitbuf23a(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) -{ - unsigned long irqL; - struct rtw_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; - - /* DBG_8723A("+rtw_free_xmitbuf23a\n"); */ - - if (pxmitbuf == NULL) - return _FAIL; - - if (pxmitbuf->sctx) { - DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__); - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE); - } - - if (pxmitbuf->ext_tag) { - rtw_free_xmitbuf_ext23a(pxmitpriv, pxmitbuf); - } else { - spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL); - - list_del_init(&pxmitbuf->list); - - list_add_tail(&pxmitbuf->list, - get_list_head(pfree_xmitbuf_queue)); - - pxmitpriv->free_xmitbuf_cnt++; - spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL); - } - - return _SUCCESS; -} - -static void rtw_init_xmitframe(struct xmit_frame *pxframe) -{ - if (pxframe != NULL) { - /* default value setting */ - pxframe->buf_addr = NULL; - pxframe->pxmitbuf = NULL; - - memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib)); - /* pxframe->attrib.psta = NULL; */ - - pxframe->frame_tag = DATA_FRAMETAG; - - pxframe->pkt = NULL; - pxframe->pkt_offset = 1;/* default use pkt_offset to fill tx desc */ - - pxframe->ack_report = 0; - } -} - -/* -Calling context: -1. OS_TXENTRY -2. RXENTRY (rx_thread or RX_ISR/RX_CallBack) - -If we turn on USE_RXTHREAD, then, no need for critical section. -Otherwise, we must use _enter/_exit critical to protect free_xmit_queue... - -Must be very very cautious... - -*/ -static struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv) -{ - struct xmit_frame *pxframe; - struct rtw_queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue; - - spin_lock_bh(&pfree_xmit_queue->lock); - - pxframe = list_first_entry_or_null(&pfree_xmit_queue->queue, - struct xmit_frame, list); - if (!pxframe) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe:%d\n", - pxmitpriv->free_xmitframe_cnt); - } else { - list_del_init(&pxframe->list); - pxmitpriv->free_xmitframe_cnt--; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe():free_xmitframe_cnt =%d\n", - pxmitpriv->free_xmitframe_cnt); - } - - spin_unlock_bh(&pfree_xmit_queue->lock); - - rtw_init_xmitframe(pxframe); - - return pxframe; -} - -struct xmit_frame *rtw_alloc_xmitframe23a_ext(struct xmit_priv *pxmitpriv) -{ - struct xmit_frame *pxframe; - struct rtw_queue *queue = &pxmitpriv->free_xframe_ext_queue; - - spin_lock_bh(&queue->lock); - - pxframe = list_first_entry_or_null(&queue->queue, - struct xmit_frame, list); - if (!pxframe) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe23a_ext:%d\n", - pxmitpriv->free_xframe_ext_cnt); - } else { - list_del_init(&pxframe->list); - pxmitpriv->free_xframe_ext_cnt--; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe23a_ext():free_xmitframe_cnt =%d\n", - pxmitpriv->free_xframe_ext_cnt); - } - - spin_unlock_bh(&queue->lock); - - rtw_init_xmitframe(pxframe); - - return pxframe; -} - -s32 rtw_free_xmitframe23a(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe) -{ - struct rtw_queue *queue = NULL; - struct rtw_adapter *padapter = pxmitpriv->adapter; - struct sk_buff *pndis_pkt = NULL; - - if (pxmitframe == NULL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "====== rtw_free_xmitframe23a():pxmitframe == NULL!!!!!!!!!!\n"); - goto exit; - } - - if (pxmitframe->pkt) { - pndis_pkt = pxmitframe->pkt; - pxmitframe->pkt = NULL; - } - - if (pxmitframe->ext_tag == 0) - queue = &pxmitpriv->free_xmit_queue; - else if (pxmitframe->ext_tag == 1) - queue = &pxmitpriv->free_xframe_ext_queue; - - if (!queue) - goto check_pkt_complete; - spin_lock_bh(&queue->lock); - - list_del_init(&pxmitframe->list); - list_add_tail(&pxmitframe->list, get_list_head(queue)); - if (pxmitframe->ext_tag == 0) { - pxmitpriv->free_xmitframe_cnt++; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, - "rtw_free_xmitframe23a():free_xmitframe_cnt =%d\n", - pxmitpriv->free_xmitframe_cnt); - } else if (pxmitframe->ext_tag == 1) { - pxmitpriv->free_xframe_ext_cnt++; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, - "rtw_free_xmitframe23a():free_xframe_ext_cnt =%d\n", - pxmitpriv->free_xframe_ext_cnt); - } - - spin_unlock_bh(&queue->lock); - -check_pkt_complete: - - if (pndis_pkt) - rtw_os_pkt_complete23a(padapter, pndis_pkt); - -exit: - - return _SUCCESS; -} - -void rtw_free_xmitframe_queue23a(struct xmit_priv *pxmitpriv, - struct rtw_queue *pframequeue) -{ - struct list_head *phead; - struct xmit_frame *pxmitframe, *ptmp; - - spin_lock_bh(&pframequeue->lock); - phead = get_list_head(pframequeue); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - spin_unlock_bh(&pframequeue->lock); - -} - -int rtw_xmitframe_enqueue23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - if (rtw_xmit23a_classifier(padapter, pxmitframe) == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "rtw_xmitframe_enqueue23a: drop xmit pkt for classifier fail\n"); - return _FAIL; - } - - return _SUCCESS; -} - -static struct xmit_frame * -dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit, - struct tx_servq *ptxservq, struct rtw_queue *pframe_queue) -{ - struct list_head *phead; - struct xmit_frame *pxmitframe = NULL; - - phead = get_list_head(pframe_queue); - - if (!list_empty(phead)) { - pxmitframe = list_first_entry(phead, struct xmit_frame, list); - list_del_init(&pxmitframe->list); - ptxservq->qcnt--; - } - return pxmitframe; -} - -struct xmit_frame * -rtw_dequeue_xframe23a(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit_i, - int entry) -{ - struct list_head *sta_phead; - struct hw_xmit *phwxmit; - struct tx_servq *ptxservq = NULL, *ptmp; - struct rtw_queue *pframe_queue = NULL; - struct xmit_frame *pxmitframe = NULL; - struct rtw_adapter *padapter = pxmitpriv->adapter; - struct registry_priv *pregpriv = &padapter->registrypriv; - int i, inx[4]; - - inx[0] = 0; - inx[1] = 1; - inx[2] = 2; - inx[3] = 3; - if (pregpriv->wifi_spec == 1) { - int j; - - for (j = 0; j < 4; j++) - inx[j] = pxmitpriv->wmm_para_seq[j]; - } - - spin_lock_bh(&pxmitpriv->lock); - - for (i = 0; i < entry; i++) { - phwxmit = phwxmit_i + inx[i]; - - sta_phead = get_list_head(phwxmit->sta_queue); - list_for_each_entry_safe(ptxservq, ptmp, sta_phead, - tx_pending) { - pframe_queue = &ptxservq->sta_pending; - - pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, ptxservq, pframe_queue); - - if (pxmitframe) { - phwxmit->accnt--; - - /* Remove sta node when there is no pending packets. */ - /* must be done after get_next and - before break */ - if (list_empty(&pframe_queue->queue)) - list_del_init(&ptxservq->tx_pending); - goto exit; - } - } - } -exit: - spin_unlock_bh(&pxmitpriv->lock); - return pxmitframe; -} - -struct tx_servq *rtw_get_sta_pending23a(struct rtw_adapter *padapter, struct sta_info *psta, int up, u8 *ac) -{ - struct tx_servq *ptxservq = NULL; - - switch (up) { - case 1: - case 2: - ptxservq = &psta->sta_xmitpriv.bk_q; - *(ac) = 3; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : BK\n"); - break; - case 4: - case 5: - ptxservq = &psta->sta_xmitpriv.vi_q; - *(ac) = 1; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : VI\n"); - break; - case 6: - case 7: - ptxservq = &psta->sta_xmitpriv.vo_q; - *(ac) = 0; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : VO\n"); - break; - case 0: - case 3: - default: - ptxservq = &psta->sta_xmitpriv.be_q; - *(ac) = 2; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : BE\n"); - break; - } - return ptxservq; -} - -/* - * Will enqueue pxmitframe to the proper queue, - * and indicate it to xx_pending list..... - */ -int rtw_xmit23a_classifier(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - struct sta_info *psta; - struct tx_servq *ptxservq; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; - u8 ac_index; - int res = _SUCCESS; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - } - if (psta == NULL) { - res = _FAIL; - DBG_8723A("rtw_xmit23a_classifier: psta == NULL\n"); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "rtw_xmit23a_classifier: psta == NULL\n"); - goto exit; - } - if (!(psta->state & _FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, - psta->state); - return _FAIL; - } - ptxservq = rtw_get_sta_pending23a(padapter, psta, pattrib->priority, - (u8 *)(&ac_index)); - - if (list_empty(&ptxservq->tx_pending)) { - list_add_tail(&ptxservq->tx_pending, - get_list_head(phwxmits[ac_index].sta_queue)); - } - - list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending)); - ptxservq->qcnt++; - phwxmits[ac_index].accnt++; -exit: - return res; -} - -void rtw_alloc_hwxmits23a(struct rtw_adapter *padapter) -{ - struct hw_xmit *hwxmits; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int size; - - pxmitpriv->hwxmit_entry = HWXMIT_ENTRY; - - size = sizeof(struct hw_xmit) * (pxmitpriv->hwxmit_entry + 1); - pxmitpriv->hwxmits = kzalloc(size, GFP_KERNEL); - - hwxmits = pxmitpriv->hwxmits; - - if (pxmitpriv->hwxmit_entry == 5) { - /* pxmitpriv->bmc_txqueue.head = 0; */ - /* hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue; */ - hwxmits[0] .sta_queue = &pxmitpriv->bm_pending; - - /* pxmitpriv->vo_txqueue.head = 0; */ - /* hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue; */ - hwxmits[1] .sta_queue = &pxmitpriv->vo_pending; - - /* pxmitpriv->vi_txqueue.head = 0; */ - /* hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue; */ - hwxmits[2] .sta_queue = &pxmitpriv->vi_pending; - - /* pxmitpriv->bk_txqueue.head = 0; */ - /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */ - hwxmits[3] .sta_queue = &pxmitpriv->bk_pending; - - /* pxmitpriv->be_txqueue.head = 0; */ - /* hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue; */ - hwxmits[4] .sta_queue = &pxmitpriv->be_pending; - - } else if (pxmitpriv->hwxmit_entry == 4) { - - /* pxmitpriv->vo_txqueue.head = 0; */ - /* hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue; */ - hwxmits[0] .sta_queue = &pxmitpriv->vo_pending; - - /* pxmitpriv->vi_txqueue.head = 0; */ - /* hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue; */ - hwxmits[1] .sta_queue = &pxmitpriv->vi_pending; - - /* pxmitpriv->be_txqueue.head = 0; */ - /* hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue; */ - hwxmits[2] .sta_queue = &pxmitpriv->be_pending; - - /* pxmitpriv->bk_txqueue.head = 0; */ - /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */ - hwxmits[3] .sta_queue = &pxmitpriv->bk_pending; - } else { - - } -} - -void rtw_free_hwxmits23a(struct rtw_adapter *padapter) -{ - struct hw_xmit *hwxmits; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - hwxmits = pxmitpriv->hwxmits; - kfree(hwxmits); -} - -void rtw_init_hwxmits23a(struct hw_xmit *phwxmit, int entry) -{ - int i; - - for (i = 0; i < entry; i++, phwxmit++) - phwxmit->accnt = 0; -} - -u32 rtw_get_ff_hwaddr23a(struct xmit_frame *pxmitframe) -{ - u32 addr; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - switch (pattrib->qsel) { - case 0: - case 3: - addr = BE_QUEUE_INX; - break; - case 1: - case 2: - addr = BK_QUEUE_INX; - break; - case 4: - case 5: - addr = VI_QUEUE_INX; - break; - case 6: - case 7: - addr = VO_QUEUE_INX; - break; - case 0x10: - addr = BCN_QUEUE_INX; - break; - case 0x11:/* BC/MC in PS (HIQ) */ - addr = HIGH_QUEUE_INX; - break; - case 0x12: - default: - addr = MGT_QUEUE_INX; - break; - } - - return addr; -} - -/* - * The main transmit(tx) entry - * - * Return - * 1 enqueue - * 0 success, hardware will handle this xmit frame(packet) - * <0 fail - */ -int rtw_xmit23a(struct rtw_adapter *padapter, struct sk_buff *skb) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_frame *pxmitframe = NULL; - int res; - - pxmitframe = rtw_alloc_xmitframe(pxmitpriv); - - if (pxmitframe == NULL) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, - "rtw_xmit23a: no more pxmitframe\n"); - return -1; - } - - res = update_attrib(padapter, skb, &pxmitframe->attrib); - - if (res == _FAIL) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, - "rtw_xmit23a: update attrib fail\n"); - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - return -1; - } - pxmitframe->pkt = skb; - - pxmitframe->attrib.qsel = pxmitframe->attrib.priority; - -#ifdef CONFIG_8723AU_AP_MODE - spin_lock_bh(&pxmitpriv->lock); - if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) { - spin_unlock_bh(&pxmitpriv->lock); - return 1; - } - spin_unlock_bh(&pxmitpriv->lock); -#endif - - if (rtl8723au_hal_xmit(padapter, pxmitframe) == false) - return 1; - - return 0; -} - -#if defined(CONFIG_8723AU_AP_MODE) - -int xmitframe_enqueue_for_sleeping_sta23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe) -{ - int ret = false; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return ret; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - } - - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return false; - } - - if (!(psta->state & _FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, - psta->state); - return false; - } - - if (pattrib->triggered == 1) { - if (bmcst) - pattrib->qsel = 0x11;/* HIQ */ - return ret; - } - - if (bmcst) { - spin_lock_bh(&psta->sleep_q.lock); - - if (pstapriv->sta_dz_bitmap) { - /* if anyone sta is in ps mode */ - list_del_init(&pxmitframe->list); - - /* spin_lock_bh(&psta->sleep_q.lock); */ - - list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q)); - - psta->sleepq_len++; - - pstapriv->tim_bitmap |= BIT(0);/* */ - pstapriv->sta_dz_bitmap |= BIT(0); - - /* DBG_8723A("enqueue, sq_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */ - - /* tx bc/mc packets after update bcn */ - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - - /* spin_unlock_bh(&psta->sleep_q.lock); */ - - ret = true; - - } - - spin_unlock_bh(&psta->sleep_q.lock); - - return ret; - - } - - spin_lock_bh(&psta->sleep_q.lock); - - if (psta->state&WIFI_SLEEP_STATE) { - u8 wmmps_ac = 0; - - if (pstapriv->sta_dz_bitmap & CHKBIT(psta->aid)) { - list_del_init(&pxmitframe->list); - - /* spin_lock_bh(&psta->sleep_q.lock); */ - - list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q)); - - psta->sleepq_len++; - - switch (pattrib->priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(0); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(0); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(0); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(0); - break; - } - - if (wmmps_ac) - psta->sleepq_ac_len++; - - if (((psta->has_legacy_ac) && (!wmmps_ac)) || - ((!psta->has_legacy_ac) && (wmmps_ac))) { - pstapriv->tim_bitmap |= CHKBIT(psta->aid); - - if (psta->sleepq_len == 1) { - /* update BCN for TIM IE */ - update_beacon23a(padapter, WLAN_EID_TIM, - NULL, false); - } - } - - /* spin_unlock_bh(&psta->sleep_q.lock); */ - - /* if (psta->sleepq_len > (NR_XMITFRAME>>3)) */ - /* */ - /* wakeup_sta_to_xmit23a(padapter, psta); */ - /* */ - - ret = true; - - } - - } - - spin_unlock_bh(&psta->sleep_q.lock); - - return ret; -} - -static void -dequeue_xmitframes_to_sleeping_queue(struct rtw_adapter *padapter, - struct sta_info *psta, - struct rtw_queue *pframequeue) -{ - int ret; - struct list_head *phead; - u8 ac_index; - struct tx_servq *ptxservq; - struct pkt_attrib *pattrib; - struct xmit_frame *pxmitframe, *ptmp; - struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; - - phead = get_list_head(pframequeue); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - ret = xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe); - - if (ret == true) { - pattrib = &pxmitframe->attrib; - - ptxservq = rtw_get_sta_pending23a(padapter, psta, pattrib->priority, (u8 *)(&ac_index)); - - ptxservq->qcnt--; - phwxmits[ac_index].accnt--; - } else { - /* DBG_8723A("xmitframe_enqueue_for_sleeping_sta23a return false\n"); */ - } - } -} - -void stop_sta_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct sta_info *psta_bmc; - struct sta_xmit_priv *pstaxmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - pstaxmitpriv = &psta->sta_xmitpriv; - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - - spin_lock_bh(&pxmitpriv->lock); - - psta->state |= WIFI_SLEEP_STATE; - - pstapriv->sta_dz_bitmap |= CHKBIT(psta->aid); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending); - list_del_init(&pstaxmitpriv->vo_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vi_q.sta_pending); - list_del_init(&pstaxmitpriv->vi_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, - &pstaxmitpriv->be_q.sta_pending); - list_del_init(&pstaxmitpriv->be_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, - &pstaxmitpriv->bk_q.sta_pending); - list_del_init(&pstaxmitpriv->bk_q.tx_pending); - - /* for BC/MC Frames */ - pstaxmitpriv = &psta_bmc->sta_xmitpriv; - dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc, - &pstaxmitpriv->be_q.sta_pending); - list_del_init(&pstaxmitpriv->be_q.tx_pending); - - spin_unlock_bh(&pxmitpriv->lock); -} - -void wakeup_sta_to_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - u8 update_mask = 0, wmmps_ac = 0; - struct sta_info *psta_bmc; - struct list_head *phead; - struct xmit_frame *pxmitframe = NULL, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - phead = get_list_head(&psta->sleep_q); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - list_del_init(&pxmitframe->list); - - switch (pxmitframe->attrib.priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(1); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(1); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(1); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(1); - break; - } - - psta->sleepq_len--; - if (psta->sleepq_len > 0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - if (wmmps_ac) { - psta->sleepq_ac_len--; - if (psta->sleepq_ac_len > 0) { - pxmitframe->attrib.mdata = 1; - pxmitframe->attrib.eosp = 0; - } else { - pxmitframe->attrib.mdata = 0; - pxmitframe->attrib.eosp = 1; - } - } - - pxmitframe->attrib.triggered = 1; - rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe); - } - - if (psta->sleepq_len == 0) { - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - - /* update BCN for TIM IE */ - update_mask = BIT(0); - - if (psta->state&WIFI_SLEEP_STATE) - psta->state ^= WIFI_SLEEP_STATE; - - if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { - psta->expire_to = pstapriv->expire_to; - psta->state ^= WIFI_STA_ALIVE_CHK_STATE; - } - - pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid); - } - /* spin_unlock_bh(&psta->sleep_q.lock); */ - spin_unlock_bh(&pxmitpriv->lock); - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - if (!psta_bmc) - return; - - if ((pstapriv->sta_dz_bitmap&0xfffe) == 0x0) { - /* no any sta in ps mode */ - spin_lock_bh(&pxmitpriv->lock); - phead = get_list_head(&psta_bmc->sleep_q); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - list_del_init(&pxmitframe->list); - - psta_bmc->sleepq_len--; - if (psta_bmc->sleepq_len > 0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe); - } - if (psta_bmc->sleepq_len == 0) { - pstapriv->tim_bitmap &= ~BIT(0); - pstapriv->sta_dz_bitmap &= ~BIT(0); - - /* update BCN for TIM IE */ - /* update_BCNTIM(padapter); */ - update_mask |= BIT(1); - } - /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */ - spin_unlock_bh(&pxmitpriv->lock); - } - - if (update_mask) - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); -} - -void xmit_delivery_enabled_frames23a(struct rtw_adapter *padapter, - struct sta_info *psta) -{ - u8 wmmps_ac = 0; - struct list_head *phead; - struct xmit_frame *pxmitframe, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - /* spin_lock_bh(&psta->sleep_q.lock); */ - spin_lock_bh(&pxmitpriv->lock); - phead = get_list_head(&psta->sleep_q); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - switch (pxmitframe->attrib.priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(1); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(1); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(1); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(1); - break; - } - - if (!wmmps_ac) - continue; - - list_del_init(&pxmitframe->list); - - psta->sleepq_len--; - psta->sleepq_ac_len--; - - if (psta->sleepq_ac_len > 0) { - pxmitframe->attrib.mdata = 1; - pxmitframe->attrib.eosp = 0; - } else { - pxmitframe->attrib.mdata = 0; - pxmitframe->attrib.eosp = 1; - } - - pxmitframe->attrib.triggered = 1; - - rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe); - - if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) && - (wmmps_ac)) { - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - - /* update BCN for TIM IE */ - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - } - } - spin_unlock_bh(&pxmitpriv->lock); -} - -#endif - -void rtw_sctx_init23a(struct submit_ctx *sctx, int timeout_ms) -{ - sctx->timeout_ms = timeout_ms; - init_completion(&sctx->done); - sctx->status = RTW_SCTX_SUBMITTED; -} - -int rtw_sctx_wait23a(struct submit_ctx *sctx) -{ - int ret = _FAIL; - unsigned long expire; - int status = 0; - - expire = sctx->timeout_ms ? msecs_to_jiffies(sctx->timeout_ms) : - MAX_SCHEDULE_TIMEOUT; - if (!wait_for_completion_timeout(&sctx->done, expire)) { - /* timeout, do something?? */ - status = RTW_SCTX_DONE_TIMEOUT; - DBG_8723A("%s timeout\n", __func__); - } else { - status = sctx->status; - } - - if (status == RTW_SCTX_DONE_SUCCESS) - ret = _SUCCESS; - - return ret; -} - -static bool rtw_sctx_chk_waring_status(int status) -{ - switch (status) { - case RTW_SCTX_DONE_UNKNOWN: - case RTW_SCTX_DONE_BUF_ALLOC: - case RTW_SCTX_DONE_BUF_FREE: - case RTW_SCTX_DONE_DRV_STOP: - case RTW_SCTX_DONE_DEV_REMOVE: - return true; - default: - return false; - } -} - -void rtw23a_sctx_done_err(struct submit_ctx **sctx, int status) -{ - if (*sctx) { - if (rtw_sctx_chk_waring_status(status)) - DBG_8723A("%s status:%d\n", __func__, status); - (*sctx)->status = status; - complete(&(*sctx)->done); - *sctx = NULL; - } -} - -int rtw_ack_tx_wait23a(struct xmit_priv *pxmitpriv, u32 timeout_ms) -{ - struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops; - - pack_tx_ops->timeout_ms = timeout_ms; - pack_tx_ops->status = RTW_SCTX_SUBMITTED; - - return rtw_sctx_wait23a(pack_tx_ops); -} - |