[PATCH 08/20] wifi: mac80211: simplify ieee80211_sta_rx_bw_to_chan_width()

Johannes Berg
2026-04-15T12:45:24Z

This function is only called for at least HT capable stations,
so doesn't need to differentiate 20/20_NOHT. Also, the check
for VHT 160 MHz support is wrong, since a station could have
support for both and the AP is using 80+80, but nothing cares
anyway, so we don't need that.

Simplify the function and move it to util.c since it now no
longer is related to VHT, and also doesn't need a station.

Also use the new function in ieee80211_get_sta_bw() for the
chandef calculations, it just needs to handle the 20/20-noht
separately; while at it fix that to handle HE stations.

Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/chan.c | 38 +++++++++++---------------------------
net/mac80211/ht.c | 3 +--
net/mac80211/ieee80211_i.h | 5 +++--
net/mac80211/util.c | 19 +++++++++++++++++++
net/mac80211/vht.c | 34 +---------------------------------
5 files changed, 35 insertions(+), 64 deletions(-)

diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 5e93405d70a3..b3d810e3691f 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -460,33 +460,17 @@ ieee80211_get_sta_bw(struct sta_info *sta, struct ieee80211_link_data *link)
*/
width = _ieee80211_sta_cap_rx_bw(link_sta, &link->conf->chanreq.oper);

- switch (width) {
- case IEEE80211_STA_RX_BW_20:
- if (link_sta->pub->ht_cap.ht_supported)
- return NL80211_CHAN_WIDTH_20;
- else
- return NL80211_CHAN_WIDTH_20_NOHT;
- case IEEE80211_STA_RX_BW_40:
- return NL80211_CHAN_WIDTH_40;
- case IEEE80211_STA_RX_BW_80:
- return NL80211_CHAN_WIDTH_80;
- case IEEE80211_STA_RX_BW_160:
- /*
- * This applied for both 160 and 80+80. since we use
- * the returned value to consider degradation of
- * ctx->conf.min_def, we have to make sure to take
- * the bigger one (NL80211_CHAN_WIDTH_160).
- * Otherwise we might try degrading even when not
- * needed, as the max required sta_bw returned (80+80)
- * might be smaller than the configured bw (160).
- */
- return NL80211_CHAN_WIDTH_160;
- case IEEE80211_STA_RX_BW_320:
- return NL80211_CHAN_WIDTH_320;
- default:
- WARN_ON(1);
- return NL80211_CHAN_WIDTH_20;
- }
+ if (width == IEEE80211_STA_RX_BW_20 &&
+ !link_sta->pub->ht_cap.ht_supported &&
+ !link_sta->pub->he_cap.has_he)
+ return NL80211_CHAN_WIDTH_20_NOHT;
+
+ /*
+ * This returns 160 for both 160 and 80+80. Since we use
+ * the returned value to consider narrowing for
+ * ctx->conf.min_def, that's correct and necessary.
+ */
+ return ieee80211_sta_rx_bw_to_chan_width(width);
}

static enum nl80211_chan_width
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 7d587f968a7f..3775d57d6c22 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -642,8 +642,7 @@ void ieee80211_ht_handle_chanwidth_notif(struct ieee80211_local *local,

link_sta->pub->bandwidth = new_bw;
sband = local->hw.wiphy->bands[band];
- sta_opmode.bw =
- ieee80211_sta_rx_bw_to_chan_width(link_sta);
+ sta_opmode.bw = ieee80211_sta_rx_bw_to_chan_width(new_bw);
sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED;

rate_control_rate_update(local, sband, link_sta,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 029600b3b7c0..3ab8368acaf9 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2329,8 +2329,6 @@ void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta_vht_cap *vht_cap);
void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
u16 vht_mask[NL80211_VHT_NSS_MAX]);
-enum nl80211_chan_width
-ieee80211_sta_rx_bw_to_chan_width(struct link_sta_info *sta);

/* HE */
void
@@ -2716,6 +2714,9 @@ void ieee80211_add_s1g_capab_ie(struct ieee80211_sub_if_data *sdata,
void ieee80211_add_aid_request_ie(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);

+enum nl80211_chan_width
+ieee80211_sta_rx_bw_to_chan_width(enum ieee80211_sta_rx_bandwidth bw);
+
/* element building in SKBs */
int ieee80211_put_srates_elem(struct sk_buff *skb,
const struct ieee80211_supported_band *sband,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index b093bc203c81..a2ca8fd0c78a 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3840,6 +3840,25 @@ void ieee80211_chandef_downgrade(struct cfg80211_chan_def *c,
WARN_ON_ONCE(!cfg80211_chandef_valid(c));
}

+enum nl80211_chan_width
+ieee80211_sta_rx_bw_to_chan_width(enum ieee80211_sta_rx_bandwidth bw)
+{
+ switch (bw) {
+ case IEEE80211_STA_RX_BW_20:
+ return NL80211_CHAN_WIDTH_20;
+ case IEEE80211_STA_RX_BW_40:
+ return NL80211_CHAN_WIDTH_40;
+ case IEEE80211_STA_RX_BW_80:
+ return NL80211_CHAN_WIDTH_80;
+ case IEEE80211_STA_RX_BW_160:
+ return NL80211_CHAN_WIDTH_160;
+ case IEEE80211_STA_RX_BW_320:
+ return NL80211_CHAN_WIDTH_320;
+ default:
+ return NL80211_CHAN_WIDTH_20;
+ }
+}
+
int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
struct cfg80211_csa_settings *csa_settings)
{
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index c25190bc7c5c..17f3f281abe1 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -433,38 +433,6 @@ _ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta,
link_sta->rx_omi_bw_rx);
}

-enum nl80211_chan_width
-ieee80211_sta_rx_bw_to_chan_width(struct link_sta_info *link_sta)
-{
- enum ieee80211_sta_rx_bandwidth cur_bw =
- link_sta->pub->bandwidth;
- struct ieee80211_sta_vht_cap *vht_cap =
- &link_sta->pub->vht_cap;
- u32 cap_width;
-
- switch (cur_bw) {
- case IEEE80211_STA_RX_BW_20:
- if (!link_sta->pub->ht_cap.ht_supported)
- return NL80211_CHAN_WIDTH_20_NOHT;
- else
- return NL80211_CHAN_WIDTH_20;
- case IEEE80211_STA_RX_BW_40:
- return NL80211_CHAN_WIDTH_40;
- case IEEE80211_STA_RX_BW_80:
- return NL80211_CHAN_WIDTH_80;
- case IEEE80211_STA_RX_BW_160:
- cap_width =
- vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
-
- if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
- return NL80211_CHAN_WIDTH_160;
-
- return NL80211_CHAN_WIDTH_80P80;
- default:
- return NL80211_CHAN_WIDTH_20;
- }
-}
-
/* FIXME: rename/move - this deals with everything not just VHT */
enum ieee80211_sta_rx_bandwidth
_ieee80211_sta_cur_vht_bw(struct link_sta_info *link_sta,
@@ -671,7 +639,7 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
new_bw = ieee80211_sta_cur_vht_bw(link_sta);
if (new_bw != link_sta->pub->bandwidth) {
link_sta->pub->bandwidth = new_bw;
- sta_opmode.bw = ieee80211_sta_rx_bw_to_chan_width(link_sta);
+ sta_opmode.bw = ieee80211_sta_rx_bw_to_chan_width(new_bw);
changed |= IEEE80211_RC_BW_CHANGED;
sta_opmode.changed |= STA_OPMODE_MAX_BW_CHANGED;
}
--
2.53.0