summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c76
1 files changed, 53 insertions, 23 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index aaa7e3c561a0..0f01b62357c6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -227,14 +227,18 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
static const u8 he_if_types_ext_capa_sta[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
- [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
+ [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF |
+ WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB,
+ [8] = WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB,
};
static const u8 tm_if_types_ext_capa_sta[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT |
WLAN_EXT_CAPA3_TIMING_MEASUREMENT_SUPPORT,
- [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
+ [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF |
+ WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB,
+ [8] = WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB,
[9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
};
@@ -301,6 +305,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
ieee80211_hw_set(hw, BUFF_MMPDU_TXQ);
ieee80211_hw_set(hw, STA_MMPDU_TXQ);
+ /* Set this early since we need to have it for the check below */
+ if (mvm->mld_api_is_used &&
+ mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;
+
/* With MLD FW API, it tracks timing by itself,
* no need for any timing from the host
*/
@@ -409,6 +418,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
+ wiphy_ext_feature_set(hw->wiphy,
+ NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT);
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_FTM_CALIBRATED)) {
@@ -1061,6 +1072,9 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
mvm->rx_ba_sessions = 0;
mvm->fwrt.dump.conf = FW_DBG_INVALID;
mvm->monitor_on = false;
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ mvm->beacon_inject_active = false;
+#endif
/* keep statistics ticking */
iwl_mvm_accu_radio_stats(mvm);
@@ -3305,8 +3319,8 @@ void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
lockdep_is_held(&mvm->mutex));
sta_id = link_sta->sta_id;
if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[sta_id])) {
- rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id],
- ERR_PTR(-ENOENT));
+ RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta_id],
+ ERR_PTR(-ENOENT));
RCU_INIT_POINTER(mvm->fw_id_to_link_sta[sta_id], NULL);
}
}
@@ -3568,24 +3582,22 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
*/
static void iwl_mvm_rs_rate_init_all_links(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- bool update)
+ struct ieee80211_sta *sta)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
unsigned int link_id;
for_each_mvm_vif_valid_link(mvmvif, link_id) {
struct ieee80211_bss_conf *conf =
- link_conf_dereference_protected(vif, link_id);
+ link_conf_dereference_check(vif, link_id);
struct ieee80211_link_sta *link_sta =
- link_sta_dereference_protected(sta, link_id);
+ link_sta_dereference_check(sta, link_id);
if (!conf || !link_sta || !mvmvif->link[link_id]->phy_ctxt)
continue;
- iwl_mvm_rs_rate_init(mvm, sta, conf, link_sta,
- mvmvif->link[link_id]->phy_ctxt->channel->band,
- update);
+ iwl_mvm_rs_rate_init(mvm, vif, sta, conf, link_sta,
+ mvmvif->link[link_id]->phy_ctxt->channel->band);
}
}
@@ -3662,6 +3674,7 @@ iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_mvm_sta_state_ops *callbacks)
{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
unsigned int i;
int ret;
@@ -3697,6 +3710,9 @@ iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm,
}
ieee80211_sta_recalc_aggregates(sta);
+ if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
+ mvmvif->ap_sta = sta;
+
return 0;
}
@@ -3753,7 +3769,7 @@ iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw,
}
out:
- iwl_mvm_rs_rate_init_all_links(mvm, vif, sta, false);
+ iwl_mvm_rs_rate_init_all_links(mvm, vif, sta);
return callbacks->update_sta(mvm, vif, sta);
}
@@ -3786,7 +3802,9 @@ iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
iwl_mvm_mei_host_associated(mvm, vif, mvm_sta);
}
- iwl_mvm_rs_rate_init_all_links(mvm, vif, sta, true);
+ mvm_sta->authorized = true;
+
+ iwl_mvm_rs_rate_init_all_links(mvm, vif, sta);
return 0;
}
@@ -3798,14 +3816,17 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
struct iwl_mvm_sta_state_ops *callbacks)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
int ret;
lockdep_assert_held(&mvm->mutex);
+ mvmsta->authorized = false;
+
/* once we move into assoc state, need to update rate scale to
* disable using wide bandwidth
*/
- iwl_mvm_rs_rate_init_all_links(mvm, vif, sta, false);
+ iwl_mvm_rs_rate_init_all_links(mvm, vif, sta);
if (!sta->tdls) {
/* Set this but don't call iwl_mvm_mac_ctxt_changed()
@@ -3924,8 +3945,10 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw,
ret = 0;
} else if (old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST) {
- if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
+ if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
iwl_mvm_stop_session_protection(mvm, vif);
+ mvmvif->ap_sta = NULL;
+ }
ret = callbacks->rm_sta(mvm, vif, sta);
if (sta->tdls) {
iwl_mvm_recalc_tdls_state(mvm, vif, false);
@@ -3968,15 +3991,11 @@ void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u32 changed)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (changed & (IEEE80211_RC_BW_CHANGED |
IEEE80211_RC_SUPP_RATES_CHANGED |
IEEE80211_RC_NSS_CHANGED))
- iwl_mvm_rs_rate_init(mvm, sta,
- &vif->bss_conf, &sta->deflink,
- mvmvif->deflink.phy_ctxt->channel->band,
- true);
+ iwl_mvm_rs_rate_init_all_links(mvm, vif, sta);
if (vif->type == NL80211_IFTYPE_STATION &&
changed & IEEE80211_RC_NSS_CHANGED)
@@ -4094,7 +4113,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_sta *mvmsta = NULL;
- struct iwl_mvm_key_pn *ptk_pn;
+ struct iwl_mvm_key_pn *ptk_pn = NULL;
int keyidx = key->keyidx;
u32 sec_key_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0);
@@ -4252,6 +4271,10 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
if (ret) {
IWL_WARN(mvm, "set key failed\n");
key->hw_key_idx = STA_KEY_IDX_INVALID;
+ if (ptk_pn) {
+ RCU_INIT_POINTER(mvmsta->ptk_pn[keyidx], NULL);
+ kfree(ptk_pn);
+ }
/*
* can't add key for RX, but we don't need it
* in the device for TX so still return 0,
@@ -5588,6 +5611,7 @@ void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct iwl_mvm_vif *mvmvif;
struct iwl_mvm_sta *mvmsta;
struct ieee80211_sta *sta;
+ bool ap_sta_done = false;
int i;
u32 msk = 0;
@@ -5616,8 +5640,14 @@ void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (mvmsta->vif != vif)
continue;
+ if (sta == mvmvif->ap_sta) {
+ if (ap_sta_done)
+ continue;
+ ap_sta_done = true;
+ }
+
/* make sure only TDLS peers or the AP are flushed */
- WARN_ON_ONCE(i != mvmvif->deflink.ap_sta_id && !sta->tdls);
+ WARN_ON_ONCE(sta != mvmvif->ap_sta && !sta->tdls);
if (drop) {
if (iwl_mvm_flush_sta(mvm, mvmsta, false))
@@ -6129,7 +6159,7 @@ static bool iwl_mvm_mac_can_aggregate(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ if (iwl_mvm_has_new_tx_csum(mvm))
return iwl_mvm_tx_csum_bz(mvm, head, true) ==
iwl_mvm_tx_csum_bz(mvm, skb, true);