Commit 57974a55 authored by Gregory Greenman's avatar Gregory Greenman Committed by Johannes Berg

wifi: iwlwifi: mvm: refactor iwl_mvm_mac_sta_state_common()

Move code handling specific state transitions into separate handlers
and adjust them for MLO. Adjust relevant callbacks as well.
Signed-off-by: default avatarGregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230328104949.5a3f8a849723.I0670d20436858a1cd3c055e03c7528db81292811@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 2c9b9220
...@@ -1606,10 +1606,14 @@ int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal); ...@@ -1606,10 +1606,14 @@ int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal);
int iwl_mvm_flush_sta_tids(struct iwl_mvm *mvm, u32 sta_id, u16 tids); int iwl_mvm_flush_sta_tids(struct iwl_mvm *mvm, u32 sta_id, u16 tids);
/* Utils to extract sta related data */ /* Utils to extract sta related data */
__le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta); __le32 iwl_mvm_get_sta_htc_flags(struct ieee80211_sta *sta,
struct ieee80211_link_sta *link_sta);
u8 iwl_mvm_get_sta_uapsd_acs(struct ieee80211_sta *sta); u8 iwl_mvm_get_sta_uapsd_acs(struct ieee80211_sta *sta);
u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_sta *sta, u32 *_agg_size); u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta,
int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct ieee80211_bss_conf *link_conf,
u32 *_agg_size);
int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm,
struct ieee80211_link_sta *link_sta,
struct iwl_he_pkt_ext_v2 *pkt_ext); struct iwl_he_pkt_ext_v2 *pkt_ext);
void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm); void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm);
......
...@@ -641,18 +641,30 @@ int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, ...@@ -641,18 +641,30 @@ int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta) void iwl_mvm_rs_add_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta)
{ {
struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->deflink.lq_sta.rs_fw; unsigned int link_id;
IWL_DEBUG_RATE(mvm, "create station rate scale window\n"); IWL_DEBUG_RATE(mvm, "create station rate scale window\n");
lq_sta->pers.drv = mvm; for (link_id = 0; link_id < ARRAY_SIZE(mvmsta->link); link_id++) {
lq_sta->pers.sta_id = mvmsta->deflink.sta_id; struct iwl_lq_sta_rs_fw *lq_sta;
lq_sta->pers.chains = 0; struct iwl_mvm_link_sta *link =
memset(lq_sta->pers.chain_signal, 0, sizeof(lq_sta->pers.chain_signal)); rcu_dereference_protected(mvmsta->link[link_id],
lq_sta->pers.last_rssi = S8_MIN; lockdep_is_held(&mvm->mutex));
lq_sta->last_rate_n_flags = 0; if (!link)
continue;
lq_sta = &link->lq_sta.rs_fw;
lq_sta->pers.drv = mvm;
lq_sta->pers.sta_id = link->sta_id;
lq_sta->pers.chains = 0;
memset(lq_sta->pers.chain_signal, 0,
sizeof(lq_sta->pers.chain_signal));
lq_sta->pers.last_rssi = S8_MIN;
lq_sta->last_rate_n_flags = 0;
#ifdef CONFIG_MAC80211_DEBUGFS #ifdef CONFIG_MAC80211_DEBUGFS
lq_sta->pers.dbg_fixed_rate = 0; lq_sta->pers.dbg_fixed_rate = 0;
#endif #endif
}
} }
...@@ -51,26 +51,31 @@ int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, enum nl80211_iftype iftype) ...@@ -51,26 +51,31 @@ int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, enum nl80211_iftype iftype)
} }
/* Calculate the ampdu density and max size */ /* Calculate the ampdu density and max size */
u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_sta *sta, u32 *_agg_size) u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_link_sta *link_sta,
struct ieee80211_bss_conf *link_conf,
u32 *_agg_size)
{ {
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
u32 agg_size = 0, mpdu_dens = 0; u32 agg_size = 0, mpdu_dens = 0;
if (sta->deflink.ht_cap.ht_supported) if (WARN_ON(!link_sta))
mpdu_dens = sta->deflink.ht_cap.ampdu_density; return 0;
if (link_sta->ht_cap.ht_supported)
mpdu_dens = link_sta->ht_cap.ampdu_density;
if (mvm_sta->vif->bss_conf.chandef.chan->band == NL80211_BAND_6GHZ) { if (link_conf->chandef.chan->band ==
mpdu_dens = le16_get_bits(sta->deflink.he_6ghz_capa.capa, NL80211_BAND_6GHZ) {
mpdu_dens = le16_get_bits(link_sta->he_6ghz_capa.capa,
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START); IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START);
agg_size = le16_get_bits(sta->deflink.he_6ghz_capa.capa, agg_size = le16_get_bits(link_sta->he_6ghz_capa.capa,
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP); IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
} else if (sta->deflink.vht_cap.vht_supported) { } else if (link_sta->vht_cap.vht_supported) {
agg_size = sta->deflink.vht_cap.cap & agg_size = link_sta->vht_cap.cap &
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
agg_size >>= agg_size >>=
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
} else if (sta->deflink.ht_cap.ht_supported) { } else if (link_sta->ht_cap.ht_supported) {
agg_size = sta->deflink.ht_cap.ampdu_factor; agg_size = link_sta->ht_cap.ampdu_factor;
} }
/* D6.0 10.12.2 A-MPDU length limit rules /* D6.0 10.12.2 A-MPDU length limit rules
...@@ -81,10 +86,10 @@ u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_sta *sta, u32 *_agg_size) ...@@ -81,10 +86,10 @@ u32 iwl_mvm_get_sta_ampdu_dens(struct ieee80211_sta *sta, u32 *_agg_size)
* Maximum AMPDU Length Exponent Extension field in its HE * Maximum AMPDU Length Exponent Extension field in its HE
* Capabilities element * Capabilities element
*/ */
if (sta->deflink.he_cap.has_he) if (link_sta->he_cap.has_he)
agg_size += agg_size +=
u8_get_bits(sta->deflink.he_cap.he_cap_elem.mac_cap_info[3], u8_get_bits(link_sta->he_cap.he_cap_elem.mac_cap_info[3],
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK); IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK);
/* Limit to max A-MPDU supported by FW */ /* Limit to max A-MPDU supported by FW */
if (agg_size > (STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT)) if (agg_size > (STA_FLG_MAX_AGG_SIZE_4M >> STA_FLG_MAX_AGG_SIZE_SHIFT))
...@@ -200,7 +205,9 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -200,7 +205,9 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
cpu_to_le32(STA_FLG_MAX_AGG_SIZE_MSK | cpu_to_le32(STA_FLG_MAX_AGG_SIZE_MSK |
STA_FLG_AGG_MPDU_DENS_MSK); STA_FLG_AGG_MPDU_DENS_MSK);
mpdu_dens = iwl_mvm_get_sta_ampdu_dens(sta, &agg_size); mpdu_dens = iwl_mvm_get_sta_ampdu_dens(&sta->deflink,
&mvm_sta->vif->bss_conf,
&agg_size);
add_sta_cmd.station_flags |= add_sta_cmd.station_flags |=
cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT); cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT);
add_sta_cmd.station_flags |= add_sta_cmd.station_flags |=
...@@ -784,19 +791,35 @@ static int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, ...@@ -784,19 +791,35 @@ static int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id,
static int iwl_mvm_get_queue_size(struct ieee80211_sta *sta) static int iwl_mvm_get_queue_size(struct ieee80211_sta *sta)
{ {
int max_size = IWL_DEFAULT_QUEUE_SIZE;
unsigned int link_id;
/* this queue isn't used for traffic (cab_queue) */ /* this queue isn't used for traffic (cab_queue) */
if (!sta) if (!sta)
return IWL_MGMT_QUEUE_SIZE; return IWL_MGMT_QUEUE_SIZE;
/* support for 1k ba size */ rcu_read_lock();
if (sta->deflink.eht_cap.has_eht)
return IWL_DEFAULT_QUEUE_SIZE_EHT;
/* support for 256 ba size */ for (link_id = 0; link_id < ARRAY_SIZE(sta->link); link_id++) {
if (sta->deflink.he_cap.has_he) struct ieee80211_link_sta *link =
return IWL_DEFAULT_QUEUE_SIZE_HE; rcu_dereference(sta->link[link_id]);
return IWL_DEFAULT_QUEUE_SIZE; if (!link)
continue;
/* support for 1k ba size */
if (link->eht_cap.has_eht &&
max_size < IWL_DEFAULT_QUEUE_SIZE_EHT)
max_size = IWL_DEFAULT_QUEUE_SIZE_EHT;
/* support for 256 ba size */
if (link->he_cap.has_he &&
max_size < IWL_DEFAULT_QUEUE_SIZE_HE)
max_size = IWL_DEFAULT_QUEUE_SIZE_HE;
}
rcu_read_unlock();
return max_size;
} }
int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
...@@ -804,6 +827,7 @@ int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, ...@@ -804,6 +827,7 @@ int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
u8 sta_id, u8 tid, unsigned int timeout) u8 sta_id, u8 tid, unsigned int timeout)
{ {
int queue, size; int queue, size;
u32 sta_mask = 0;
if (tid == IWL_MAX_TID_COUNT) { if (tid == IWL_MAX_TID_COUNT) {
tid = IWL_MGMT_TID; tid = IWL_MGMT_TID;
...@@ -819,22 +843,45 @@ int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, ...@@ -819,22 +843,45 @@ int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm,
/* size needs to be power of 2 values for calculating read/write pointers */ /* size needs to be power of 2 values for calculating read/write pointers */
size = rounddown_pow_of_two(size); size = rounddown_pow_of_two(size);
if (sta) {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
unsigned int link_id;
for (link_id = 0;
link_id < ARRAY_SIZE(mvmsta->link);
link_id++) {
struct iwl_mvm_link_sta *link =
rcu_dereference_protected(mvmsta->link[link_id],
lockdep_is_held(&mvm->mutex));
if (!link)
continue;
sta_mask |= BIT(link->sta_id);
}
} else {
sta_mask |= BIT(sta_id);
}
if (!sta_mask)
return -EINVAL;
do { do {
queue = iwl_trans_txq_alloc(mvm->trans, 0, BIT(sta_id), queue = iwl_trans_txq_alloc(mvm->trans, 0, sta_mask,
tid, size, timeout); tid, size, timeout);
if (queue < 0) if (queue < 0)
IWL_DEBUG_TX_QUEUES(mvm, IWL_DEBUG_TX_QUEUES(mvm,
"Failed allocating TXQ of size %d for sta %d tid %d, ret: %d\n", "Failed allocating TXQ of size %d for sta mask %x tid %d, ret: %d\n",
size, sta_id, tid, queue); size, sta_mask, tid, queue);
size /= 2; size /= 2;
} while (queue < 0 && size >= 16); } while (queue < 0 && size >= 16);
if (queue < 0) if (queue < 0)
return queue; return queue;
IWL_DEBUG_TX_QUEUES(mvm, "Enabling TXQ #%d for sta %d tid %d\n", IWL_DEBUG_TX_QUEUES(mvm, "Enabling TXQ #%d for sta mask 0x%x tid %d\n",
queue, sta_id, tid); queue, sta_mask, tid);
return queue; return queue;
} }
...@@ -1657,16 +1704,28 @@ int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -1657,16 +1704,28 @@ int iwl_mvm_sta_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
mvm_sta->deflink.sta_id = sta_id;
rcu_assign_pointer(mvm_sta->link[0], &mvm_sta->deflink);
mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id, mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id,
mvmvif->color); mvmvif->color);
mvm_sta->vif = vif; mvm_sta->vif = vif;
if (!mvm->trans->trans_cfg->gen2)
mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF; /* for MLD sta_id(s) should be allocated for each link before calling
else * this function
mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF; */
if (!mvm->mld_api_is_used) {
if (WARN_ON(sta_id == IWL_MVM_INVALID_STA))
return -EINVAL;
mvm_sta->deflink.sta_id = sta_id;
rcu_assign_pointer(mvm_sta->link[0], &mvm_sta->deflink);
if (!mvm->trans->trans_cfg->gen2)
mvm_sta->max_agg_bufsize =
LINK_QUAL_AGG_FRAME_LIMIT_DEF;
else
mvm_sta->max_agg_bufsize =
LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF;
}
mvm_sta->tt_tx_protection = false; mvm_sta->tt_tx_protection = false;
mvm_sta->sta_type = sta_type; mvm_sta->sta_type = sta_type;
...@@ -1926,11 +1985,12 @@ int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm, ...@@ -1926,11 +1985,12 @@ int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm,
* with error or success * with error or success
*/ */
bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, int *ret) struct ieee80211_sta *sta,
struct iwl_mvm_link_sta *mvm_link_sta, int *ret)
{ {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
u8 sta_id = mvm_sta->deflink.sta_id; u8 sta_id = mvm_link_sta->sta_id;
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
...@@ -1956,8 +2016,7 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -1956,8 +2016,7 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
*status = IWL_MVM_QUEUE_FREE; *status = IWL_MVM_QUEUE_FREE;
} }
if (vif->type == NL80211_IFTYPE_STATION && if (vif->type == NL80211_IFTYPE_STATION) {
mvmvif->deflink.ap_sta_id == sta_id) {
/* if associated - we can't remove the AP STA now */ /* if associated - we can't remove the AP STA now */
if (vif->cfg.assoc) if (vif->cfg.assoc)
return true; return true;
...@@ -2023,7 +2082,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, ...@@ -2023,7 +2082,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
iwl_mvm_disable_sta_queues(mvm, vif, sta); iwl_mvm_disable_sta_queues(mvm, vif, sta);
if (iwl_mvm_sta_del(mvm, vif, sta, &ret)) if (iwl_mvm_sta_del(mvm, vif, sta, &mvm_sta->deflink, &ret))
return ret; return ret;
ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->deflink.sta_id); ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->deflink.sta_id);
......
...@@ -490,7 +490,8 @@ void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm, ...@@ -490,7 +490,8 @@ void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm, int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvm_sta); struct iwl_mvm_sta *mvm_sta);
bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, int *ret); struct ieee80211_sta *sta,
struct iwl_mvm_link_sta *mvm_link_sta, int *ret);
int iwl_mvm_rm_sta(struct iwl_mvm *mvm, int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_sta *sta); struct ieee80211_sta *sta);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment