mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 10:09:10 +02:00
wifi: mac80211: clean up STA NSS handling
Move ieee80211_sta_init_nss() from VHT code to station code, and disentangle it from rate control. This way, it becomes clearer when 'rx_nss' is set up. While doing this, fix the client side code to set up link_sta->op_mode_nss instead of link_sta->pub->rx_nss for the opmode element in association response, and remove the (now wrong) comment about handling that in the function. type=cleanup ticket=none Signed-off-by: Johannes Berg <johannes.berg@intel.com> Reviewed-on: https://gerritwcs.ir.intel.com/c/iwlwifi-stack-dev/+/273695 Tested-by: iil_jenkins iil_jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM> tested: iil_jenkins iil_jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM> Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20260415144514.bef3d07beeb6.I97fb93ccc1b366110ab23de58fcd73676cdd85d6@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
ae24cf3b69
commit
e5ad38a9b2
|
|
@ -553,6 +553,8 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta)
|
|||
|
||||
memcpy(addr, sta->sta.addr, ETH_ALEN);
|
||||
|
||||
ieee80211_sta_init_nss(&sta->deflink);
|
||||
|
||||
ibss_dbg(sdata, "Adding new IBSS station %pM\n", addr);
|
||||
|
||||
sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
|
||||
|
|
|
|||
|
|
@ -2315,7 +2315,7 @@ ieee80211_sta_cur_vht_bw(struct link_sta_info *link_sta)
|
|||
{
|
||||
return _ieee80211_sta_cur_vht_bw(link_sta, NULL);
|
||||
}
|
||||
void ieee80211_sta_init_nss(struct link_sta_info *link_sta);
|
||||
|
||||
void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_link_data *link,
|
||||
struct ieee80211_mgmt *mgmt);
|
||||
|
|
|
|||
|
|
@ -470,6 +470,8 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
|
|||
elems->eht_cap, elems->eht_cap_len,
|
||||
&sta->deflink);
|
||||
|
||||
ieee80211_sta_init_nss(&sta->deflink);
|
||||
|
||||
if (bw != sta->sta.deflink.bandwidth)
|
||||
changed |= IEEE80211_RC_BW_CHANGED;
|
||||
|
||||
|
|
|
|||
|
|
@ -5749,9 +5749,9 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
|
|||
*/
|
||||
|
||||
/*
|
||||
* If an operating mode notification IE is present, override the
|
||||
* NSS calculation (that would be done in rate_control_rate_init())
|
||||
* and use the # of streams from that element.
|
||||
* If an operating mode notification element is present, set the opmode
|
||||
* NSS override to correct for the current number of spatial streams,
|
||||
* overriding the capabilities. ieee80211_sta_init_nss() uses this.
|
||||
*/
|
||||
if (elems->opmode_notif &&
|
||||
!(*elems->opmode_notif & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF)) {
|
||||
|
|
@ -5760,9 +5760,11 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
|
|||
nss = *elems->opmode_notif & IEEE80211_OPMODE_NOTIF_RX_NSS_MASK;
|
||||
nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT;
|
||||
nss += 1;
|
||||
link_sta->pub->rx_nss = nss;
|
||||
link_sta->op_mode_nss = nss;
|
||||
}
|
||||
|
||||
ieee80211_sta_init_nss(link_sta);
|
||||
|
||||
/*
|
||||
* Always handle WMM once after association regardless
|
||||
* of the first value the AP uses. Setting -1 here has
|
||||
|
|
@ -10617,7 +10619,6 @@ void ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata,
|
|||
if (add_links_data->link[link_id].status != WLAN_STATUS_SUCCESS)
|
||||
goto disconnect;
|
||||
|
||||
ieee80211_sta_init_nss(link_sta);
|
||||
if (ieee80211_sta_activate_link(sta, link_id))
|
||||
goto disconnect;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Copyright: (c) 2014 Czech Technical University in Prague
|
||||
* (c) 2014 Volkswagen Group Research
|
||||
* Copyright (C) 2022 - 2024 Intel Corporation
|
||||
* Copyright (C) 2022 - 2024, 2026 Intel Corporation
|
||||
* Author: Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz>
|
||||
* Funded by: Volkswagen Group Research
|
||||
*/
|
||||
|
|
@ -92,6 +92,8 @@ static struct sta_info *ieee80211_ocb_finish_sta(struct sta_info *sta)
|
|||
|
||||
memcpy(addr, sta->sta.addr, ETH_ALEN);
|
||||
|
||||
ieee80211_sta_init_nss(&sta->deflink);
|
||||
|
||||
ocb_dbg(sdata, "Adding new IBSS station %pM (dev=%s)\n",
|
||||
addr, sdata->name);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright 2005-2006, Devicescape Software, Inc.
|
||||
* Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2019, 2022-2025 Intel Corporation
|
||||
* Copyright (C) 2019, 2022-2026 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -38,8 +38,6 @@ void rate_control_rate_init(struct link_sta_info *link_sta)
|
|||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
|
||||
ieee80211_sta_init_nss(link_sta);
|
||||
|
||||
if (!ref)
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -3426,6 +3426,98 @@ void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id)
|
|||
sta_remove_link(sta, link_id, true);
|
||||
}
|
||||
|
||||
void ieee80211_sta_init_nss(struct link_sta_info *link_sta)
|
||||
{
|
||||
u8 ht_rx_nss = 0, vht_rx_nss = 0, he_rx_nss = 0, eht_rx_nss = 0, rx_nss;
|
||||
bool support_160;
|
||||
|
||||
if (link_sta->pub->eht_cap.has_eht) {
|
||||
int i;
|
||||
const u8 *rx_nss_mcs = (void *)&link_sta->pub->eht_cap.eht_mcs_nss_supp;
|
||||
|
||||
/* get the max nss for EHT over all possible bandwidths and mcs */
|
||||
for (i = 0; i < sizeof(struct ieee80211_eht_mcs_nss_supp); i++)
|
||||
eht_rx_nss = max_t(u8, eht_rx_nss,
|
||||
u8_get_bits(rx_nss_mcs[i],
|
||||
IEEE80211_EHT_MCS_NSS_RX));
|
||||
}
|
||||
|
||||
if (link_sta->pub->he_cap.has_he) {
|
||||
int i;
|
||||
u8 rx_mcs_80 = 0, rx_mcs_160 = 0;
|
||||
const struct ieee80211_sta_he_cap *he_cap = &link_sta->pub->he_cap;
|
||||
u16 mcs_160_map =
|
||||
le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
|
||||
u16 mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
|
||||
|
||||
for (i = 7; i >= 0; i--) {
|
||||
u8 mcs_160 = (mcs_160_map >> (2 * i)) & 3;
|
||||
|
||||
if (mcs_160 != IEEE80211_HE_MCS_NOT_SUPPORTED) {
|
||||
rx_mcs_160 = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 7; i >= 0; i--) {
|
||||
u8 mcs_80 = (mcs_80_map >> (2 * i)) & 3;
|
||||
|
||||
if (mcs_80 != IEEE80211_HE_MCS_NOT_SUPPORTED) {
|
||||
rx_mcs_80 = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
support_160 = he_cap->he_cap_elem.phy_cap_info[0] &
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
|
||||
|
||||
if (support_160)
|
||||
he_rx_nss = min(rx_mcs_80, rx_mcs_160);
|
||||
else
|
||||
he_rx_nss = rx_mcs_80;
|
||||
}
|
||||
|
||||
if (link_sta->pub->ht_cap.ht_supported) {
|
||||
if (link_sta->pub->ht_cap.mcs.rx_mask[0])
|
||||
ht_rx_nss++;
|
||||
if (link_sta->pub->ht_cap.mcs.rx_mask[1])
|
||||
ht_rx_nss++;
|
||||
if (link_sta->pub->ht_cap.mcs.rx_mask[2])
|
||||
ht_rx_nss++;
|
||||
if (link_sta->pub->ht_cap.mcs.rx_mask[3])
|
||||
ht_rx_nss++;
|
||||
/* FIXME: consider rx_highest? */
|
||||
}
|
||||
|
||||
if (link_sta->pub->vht_cap.vht_supported) {
|
||||
int i;
|
||||
u16 rx_mcs_map;
|
||||
|
||||
rx_mcs_map = le16_to_cpu(link_sta->pub->vht_cap.vht_mcs.rx_mcs_map);
|
||||
|
||||
for (i = 7; i >= 0; i--) {
|
||||
u8 mcs = (rx_mcs_map >> (2 * i)) & 3;
|
||||
|
||||
if (mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
|
||||
vht_rx_nss = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* FIXME: consider rx_highest? */
|
||||
}
|
||||
|
||||
rx_nss = max(vht_rx_nss, ht_rx_nss);
|
||||
rx_nss = max(he_rx_nss, rx_nss);
|
||||
rx_nss = max(eht_rx_nss, rx_nss);
|
||||
rx_nss = max_t(u8, 1, rx_nss);
|
||||
link_sta->capa_nss = rx_nss;
|
||||
|
||||
if (link_sta->op_mode_nss)
|
||||
link_sta->pub->rx_nss =
|
||||
min_t(u8, rx_nss, link_sta->op_mode_nss);
|
||||
else
|
||||
link_sta->pub->rx_nss = rx_nss;
|
||||
}
|
||||
|
||||
void ieee80211_sta_set_max_amsdu_subframes(struct sta_info *sta,
|
||||
const u8 *ext_capab,
|
||||
unsigned int ext_capab_len)
|
||||
|
|
|
|||
|
|
@ -997,6 +997,7 @@ void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta);
|
|||
|
||||
unsigned long ieee80211_sta_last_active(struct sta_info *sta, int link_id);
|
||||
|
||||
void ieee80211_sta_init_nss(struct link_sta_info *link_sta);
|
||||
void ieee80211_sta_set_max_amsdu_subframes(struct sta_info *sta,
|
||||
const u8 *ext_capab,
|
||||
unsigned int ext_capab_len);
|
||||
|
|
|
|||
|
|
@ -488,99 +488,6 @@ _ieee80211_sta_cur_vht_bw(struct link_sta_info *link_sta,
|
|||
return bw;
|
||||
}
|
||||
|
||||
void ieee80211_sta_init_nss(struct link_sta_info *link_sta)
|
||||
{
|
||||
u8 ht_rx_nss = 0, vht_rx_nss = 0, he_rx_nss = 0, eht_rx_nss = 0, rx_nss;
|
||||
bool support_160;
|
||||
|
||||
if (link_sta->pub->eht_cap.has_eht) {
|
||||
int i;
|
||||
const u8 *rx_nss_mcs = (void *)&link_sta->pub->eht_cap.eht_mcs_nss_supp;
|
||||
|
||||
/* get the max nss for EHT over all possible bandwidths and mcs */
|
||||
for (i = 0; i < sizeof(struct ieee80211_eht_mcs_nss_supp); i++)
|
||||
eht_rx_nss = max_t(u8, eht_rx_nss,
|
||||
u8_get_bits(rx_nss_mcs[i],
|
||||
IEEE80211_EHT_MCS_NSS_RX));
|
||||
}
|
||||
|
||||
if (link_sta->pub->he_cap.has_he) {
|
||||
int i;
|
||||
u8 rx_mcs_80 = 0, rx_mcs_160 = 0;
|
||||
const struct ieee80211_sta_he_cap *he_cap = &link_sta->pub->he_cap;
|
||||
u16 mcs_160_map =
|
||||
le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
|
||||
u16 mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
|
||||
|
||||
for (i = 7; i >= 0; i--) {
|
||||
u8 mcs_160 = (mcs_160_map >> (2 * i)) & 3;
|
||||
|
||||
if (mcs_160 != IEEE80211_HE_MCS_NOT_SUPPORTED) {
|
||||
rx_mcs_160 = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 7; i >= 0; i--) {
|
||||
u8 mcs_80 = (mcs_80_map >> (2 * i)) & 3;
|
||||
|
||||
if (mcs_80 != IEEE80211_HE_MCS_NOT_SUPPORTED) {
|
||||
rx_mcs_80 = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
support_160 = he_cap->he_cap_elem.phy_cap_info[0] &
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
|
||||
|
||||
if (support_160)
|
||||
he_rx_nss = min(rx_mcs_80, rx_mcs_160);
|
||||
else
|
||||
he_rx_nss = rx_mcs_80;
|
||||
}
|
||||
|
||||
if (link_sta->pub->ht_cap.ht_supported) {
|
||||
if (link_sta->pub->ht_cap.mcs.rx_mask[0])
|
||||
ht_rx_nss++;
|
||||
if (link_sta->pub->ht_cap.mcs.rx_mask[1])
|
||||
ht_rx_nss++;
|
||||
if (link_sta->pub->ht_cap.mcs.rx_mask[2])
|
||||
ht_rx_nss++;
|
||||
if (link_sta->pub->ht_cap.mcs.rx_mask[3])
|
||||
ht_rx_nss++;
|
||||
/* FIXME: consider rx_highest? */
|
||||
}
|
||||
|
||||
if (link_sta->pub->vht_cap.vht_supported) {
|
||||
int i;
|
||||
u16 rx_mcs_map;
|
||||
|
||||
rx_mcs_map = le16_to_cpu(link_sta->pub->vht_cap.vht_mcs.rx_mcs_map);
|
||||
|
||||
for (i = 7; i >= 0; i--) {
|
||||
u8 mcs = (rx_mcs_map >> (2 * i)) & 3;
|
||||
|
||||
if (mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
|
||||
vht_rx_nss = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* FIXME: consider rx_highest? */
|
||||
}
|
||||
|
||||
rx_nss = max(vht_rx_nss, ht_rx_nss);
|
||||
rx_nss = max(he_rx_nss, rx_nss);
|
||||
rx_nss = max(eht_rx_nss, rx_nss);
|
||||
rx_nss = max_t(u8, 1, rx_nss);
|
||||
link_sta->capa_nss = rx_nss;
|
||||
|
||||
/* that shouldn't be set yet, but we can handle it anyway */
|
||||
if (link_sta->op_mode_nss)
|
||||
link_sta->pub->rx_nss =
|
||||
min_t(u8, rx_nss, link_sta->op_mode_nss);
|
||||
else
|
||||
link_sta->pub->rx_nss = rx_nss;
|
||||
}
|
||||
|
||||
u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
|
||||
struct link_sta_info *link_sta,
|
||||
u8 opmode, enum nl80211_band band)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user