summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/sta.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c103
1 files changed, 68 insertions, 35 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 5469d634e289..3b9a343d4f67 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2015, 2018-2022 Intel Corporation
+ * Copyright (C) 2012-2015, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -60,22 +60,27 @@ u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta,
if (WARN_ON(!link_sta))
return 0;
- if (link_sta->ht_cap.ht_supported)
+ /* Note that we always use only legacy & highest supported PPDUs, so
+ * of Draft P802.11be D.30 Table 10-12a--Fields used for calculating
+ * the maximum A-MPDU size of various PPDU types in different bands,
+ * we only need to worry about the highest supported PPDU type here.
+ */
+
+ if (link_sta->ht_cap.ht_supported) {
+ agg_size = link_sta->ht_cap.ampdu_factor;
mpdu_dens = link_sta->ht_cap.ampdu_density;
+ }
- if (link_conf->chandef.chan->band ==
- NL80211_BAND_6GHZ) {
+ if (link_conf->chandef.chan->band == NL80211_BAND_6GHZ) {
+ /* overwrite HT values on 6 GHz */
mpdu_dens = le16_get_bits(link_sta->he_6ghz_capa.capa,
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START);
agg_size = le16_get_bits(link_sta->he_6ghz_capa.capa,
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
} else if (link_sta->vht_cap.vht_supported) {
- agg_size = link_sta->vht_cap.cap &
- IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
- agg_size >>=
- IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
- } else if (link_sta->ht_cap.ht_supported) {
- agg_size = link_sta->ht_cap.ampdu_factor;
+ /* if VHT supported overwrite HT value */
+ agg_size = u32_get_bits(link_sta->vht_cap.cap,
+ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK);
}
/* D6.0 10.12.2 A-MPDU length limit rules
@@ -91,10 +96,13 @@ u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta,
u8_get_bits(link_sta->he_cap.he_cap_elem.mac_cap_info[3],
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK);
+ if (link_sta->eht_cap.has_eht)
+ agg_size += u8_get_bits(link_sta->eht_cap.eht_cap_elem.mac_cap_info[1],
+ IEEE80211_EHT_MAC_CAP1_MAX_AMPDU_LEN_MASK);
+
/* Limit to max A-MPDU supported by FW */
- if (agg_size > (STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT))
- agg_size = (STA_FLG_MAX_AGG_SIZE_4M >>
- STA_FLG_MAX_AGG_SIZE_SHIFT);
+ agg_size = min_t(u32, agg_size,
+ STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT);
*_agg_size = agg_size;
return mpdu_dens;
@@ -281,7 +289,7 @@ static void iwl_mvm_rx_agg_session_expired(struct timer_list *t)
* A-MDPU and hence the timer continues to run. Then, the
* timer expires and sta is NULL.
*/
- if (!sta)
+ if (IS_ERR_OR_NULL(sta))
goto unlock;
mvm_sta = iwl_mvm_sta_from_mac80211(sta);
@@ -1679,7 +1687,7 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
memset(&cmd, 0, sizeof(cmd));
cmd.sta_id = sta->sta_id;
- if (iwl_fw_lookup_cmd_ver(mvm->fw, ADD_STA, 0) >= 12 &&
+ if (iwl_mvm_has_new_station_api(mvm->fw) &&
sta->type == IWL_STA_AUX_ACTIVITY)
cmd.mac_id_n_color = cpu_to_le32(mac_id);
else
@@ -1859,6 +1867,8 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
ret = iwl_mvm_sta_init(mvm, vif, sta, sta_id,
sta->tdls ? IWL_STA_TDLS_LINK : IWL_STA_LINK);
+ if (ret)
+ goto err;
update_fw:
ret = iwl_mvm_sta_send_to_fw(mvm, sta, sta_update, sta_flags);
@@ -2070,13 +2080,6 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
cancel_delayed_work(&mvm->tdls_cs.dwork);
}
- /*
- * Make sure that the tx response code sees the station as -EBUSY and
- * calls the drain worker.
- */
- spin_lock_bh(&mvm_sta->lock);
- spin_unlock_bh(&mvm_sta->lock);
-
return false;
}
@@ -2089,9 +2092,6 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
- if (iwl_mvm_has_new_rx_api(mvm))
- kfree(mvm_sta->dup_data);
-
ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
if (ret)
return ret;
@@ -2885,7 +2885,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
}
if (iwl_mvm_has_new_rx_api(mvm) && start) {
- u16 reorder_buf_size = buf_size * sizeof(baid_data->entries[0]);
+ u32 reorder_buf_size = buf_size * sizeof(baid_data->entries[0]);
/* sparse doesn't like the __align() so don't check */
#ifndef __CHECKER__
@@ -3785,6 +3785,9 @@ static inline u8 *iwl_mvm_get_mac_addr(struct iwl_mvm *mvm,
u8 sta_id = mvmvif->deflink.ap_sta_id;
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
lockdep_is_held(&mvm->mutex));
+ if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
+ return NULL;
+
return sta->addr;
}
@@ -3822,6 +3825,11 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
if (keyconf->cipher == WLAN_CIPHER_SUITE_TKIP) {
addr = iwl_mvm_get_mac_addr(mvm, vif, sta);
+ if (!addr) {
+ IWL_ERR(mvm, "Failed to find mac address\n");
+ return -EINVAL;
+ }
+
/* get phase 1 key from mac80211 */
ieee80211_get_key_rx_seq(keyconf, 0, &seq);
ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
@@ -4301,16 +4309,27 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
u16 queue;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_key_conf *keyconf;
+ unsigned int wdg_timeout =
+ iwl_mvm_get_wd_timeout(mvm, vif, false, false);
+ bool mld = iwl_mvm_has_mld_api(mvm->fw);
+ u32 type = mld ? STATION_TYPE_PEER : IWL_STA_LINK;
ret = iwl_mvm_allocate_int_sta(mvm, sta, 0,
- NL80211_IFTYPE_UNSPECIFIED,
- IWL_STA_LINK);
+ NL80211_IFTYPE_UNSPECIFIED, type);
if (ret)
return ret;
- ret = iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id, mvmvif->color,
- addr, sta, &queue,
- IWL_MVM_TX_FIFO_BE);
+ if (mld)
+ ret = iwl_mvm_mld_add_int_sta_with_queue(mvm, sta, addr,
+ mvmvif->deflink.fw_link_id,
+ &queue,
+ IWL_MAX_TID_COUNT,
+ &wdg_timeout);
+ else
+ ret = iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id,
+ mvmvif->color, addr, sta,
+ &queue,
+ IWL_MVM_TX_FIFO_BE);
if (ret)
goto out;
@@ -4323,9 +4342,23 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
keyconf->cipher = cipher;
memcpy(keyconf->key, key, key_len);
keyconf->keylen = key_len;
+ keyconf->flags = IEEE80211_KEY_FLAG_PAIRWISE;
+
+ if (mld) {
+ /* The MFP flag is set according to the station mfp field. Since
+ * we don't have a station, set it manually.
+ */
+ u32 key_flags =
+ iwl_mvm_get_sec_flags(mvm, vif, NULL, keyconf) |
+ IWL_SEC_KEY_FLAG_MFP;
+ u32 sta_mask = BIT(sta->sta_id);
+
+ ret = iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf);
+ } else {
+ ret = iwl_mvm_send_sta_key(mvm, sta->sta_id, keyconf, false,
+ 0, NULL, 0, 0, true);
+ }
- ret = iwl_mvm_send_sta_key(mvm, sta->sta_id, keyconf, false,
- 0, NULL, 0, 0, true);
kfree(keyconf);
return 0;
out:
@@ -4335,10 +4368,10 @@ out:
void iwl_mvm_cancel_channel_switch(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- u32 mac_id)
+ u32 id)
{
struct iwl_cancel_channel_switch_cmd cancel_channel_switch_cmd = {
- .mac_id = cpu_to_le32(mac_id),
+ .id = cpu_to_le32(id),
};
int ret;