From 979557e8794c552d94f0ff6bc11cfdadb291dead Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Fri, 26 Jul 2024 01:13:51 +0200 Subject: [PATCH] mac80211: Fix wifi throughput Backport 2 patches from upstream Linux to fix a Wifi throughput problem. Fixes: 323e249ce8ed ("mac80211: Update to version 6.1.97-1") Link: https://github.com/openwrt/openwrt/pull/16007 Signed-off-by: Hauke Mehrtens --- ...low-NSS-change-only-up-to-capability.patch | 69 +++++++ ...ack-capability-opmode-NSS-separately.patch | 186 ++++++++++++++++++ 2 files changed, 255 insertions(+) create mode 100644 package/kernel/mac80211/patches/subsys/350-v6.3-wifi-mac80211-Allow-NSS-change-only-up-to-capability.patch create mode 100644 package/kernel/mac80211/patches/subsys/351-v6.9-wifi-mac80211-track-capability-opmode-NSS-separately.patch diff --git a/package/kernel/mac80211/patches/subsys/350-v6.3-wifi-mac80211-Allow-NSS-change-only-up-to-capability.patch b/package/kernel/mac80211/patches/subsys/350-v6.3-wifi-mac80211-Allow-NSS-change-only-up-to-capability.patch new file mode 100644 index 0000000000..c8e0dd62b4 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/350-v6.3-wifi-mac80211-Allow-NSS-change-only-up-to-capability.patch @@ -0,0 +1,69 @@ +From 1b7c710a8e912d54a24742ed5a87a047be64141a Mon Sep 17 00:00:00 2001 +From: Rameshkumar Sundaram +Date: Tue, 7 Feb 2023 17:11:46 +0530 +Subject: [PATCH 350/351] wifi: mac80211: Allow NSS change only up to + capability + +Stations can update bandwidth/NSS change in +VHT action frame with action type Operating Mode Notification. +(IEEE Std 802.11-2020 - 9.4.1.53 Operating Mode field) + +For Operating Mode Notification, an RX NSS change to a value +greater than AP's maximum NSS should not be allowed. +During fuzz testing, by forcefully sending VHT Op. mode notif. +frames from STA with random rx_nss values, it is found that AP +accepts rx_nss values greater that APs maximum NSS instead of +discarding such NSS change. + +Hence allow NSS change only up to maximum NSS that is negotiated +and capped to AP's capability during association. + +Signed-off-by: Rameshkumar Sundaram +Link: https://lore.kernel.org/r/20230207114146.10567-1-quic_ramess@quicinc.com +Signed-off-by: Johannes Berg +(cherry picked from commit 57b341e9ab13e5688491bfd54f8b5502416c8905) +--- + net/mac80211/vht.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +--- a/net/mac80211/vht.c ++++ b/net/mac80211/vht.c +@@ -637,7 +637,7 @@ u32 __ieee80211_vht_handle_opmode(struct + enum ieee80211_sta_rx_bandwidth new_bw; + struct sta_opmode_info sta_opmode = {}; + u32 changed = 0; +- u8 nss; ++ u8 nss, cur_nss; + + /* ignore - no support for BF yet */ + if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF) +@@ -648,10 +648,25 @@ u32 __ieee80211_vht_handle_opmode(struct + nss += 1; + + if (link_sta->pub->rx_nss != nss) { +- link_sta->pub->rx_nss = nss; +- sta_opmode.rx_nss = nss; +- changed |= IEEE80211_RC_NSS_CHANGED; +- sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED; ++ cur_nss = link_sta->pub->rx_nss; ++ /* Reset rx_nss and call ieee80211_sta_set_rx_nss() which ++ * will set the same to max nss value calculated based on capability. ++ */ ++ link_sta->pub->rx_nss = 0; ++ ieee80211_sta_set_rx_nss(link_sta); ++ /* Do not allow an nss change to rx_nss greater than max_nss ++ * negotiated and capped to APs capability during association. ++ */ ++ if (nss <= link_sta->pub->rx_nss) { ++ link_sta->pub->rx_nss = nss; ++ sta_opmode.rx_nss = nss; ++ changed |= IEEE80211_RC_NSS_CHANGED; ++ sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED; ++ } else { ++ link_sta->pub->rx_nss = cur_nss; ++ pr_warn_ratelimited("Ignoring NSS change in VHT Operating Mode Notification from %pM with invalid nss %d", ++ link_sta->pub->addr, nss); ++ } + } + + switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) { diff --git a/package/kernel/mac80211/patches/subsys/351-v6.9-wifi-mac80211-track-capability-opmode-NSS-separately.patch b/package/kernel/mac80211/patches/subsys/351-v6.9-wifi-mac80211-track-capability-opmode-NSS-separately.patch new file mode 100644 index 0000000000..968e7171d2 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/351-v6.9-wifi-mac80211-track-capability-opmode-NSS-separately.patch @@ -0,0 +1,186 @@ +From 32d043fc10f1814e421c0ff90c0ee6b303f2821c Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 28 Feb 2024 12:01:57 +0100 +Subject: [PATCH 351/351] wifi: mac80211: track capability/opmode NSS + separately + +We're currently tracking rx_nss for each station, and that +is meant to be initialized to the capability NSS and later +reduced by the operating mode notification NSS. + +However, we're mixing up capabilities and operating mode +NSS in the same variable. This forces us to recalculate +the NSS capability on operating mode notification RX, +which is a bit strange; due to the previous fix I had to +never keep rx_nss as zero, it also means that the capa is +never taken into account properly. + +Fix all this by storing the capability value, that can be +recalculated unconditionally whenever needed, and storing +the operating mode notification NSS separately, taking it +into account when assigning the final rx_nss value. + +Cc: stable@vger.kernel.org +Fixes: dd6c064cfc3f ("wifi: mac80211: set station RX-NSS on reconfig") +Reviewed-by: Miriam Rachel Korenblit +Link: https://msgid.link/20240228120157.0e1c41924d1d.I0acaa234e0267227b7e3ef81a59117c8792116bc@changeid +Signed-off-by: Johannes Berg +(cherry picked from commit a8bca3e9371dc5e276af4168be099b2a05554c2a) +--- + net/mac80211/cfg.c | 2 +- + net/mac80211/ieee80211_i.h | 2 +- + net/mac80211/rate.c | 2 +- + net/mac80211/sta_info.h | 6 ++++- + net/mac80211/vht.c | 46 ++++++++++++++++++-------------------- + 5 files changed, 30 insertions(+), 28 deletions(-) + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1836,7 +1836,7 @@ static int sta_link_apply_parameters(str + sband->band); + } + +- ieee80211_sta_set_rx_nss(link_sta); ++ ieee80211_sta_init_nss(link_sta); + + return ret; + } +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2101,7 +2101,7 @@ enum ieee80211_sta_rx_bandwidth + ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta); + enum ieee80211_sta_rx_bandwidth + ieee80211_sta_cur_vht_bw(struct link_sta_info *link_sta); +-void ieee80211_sta_set_rx_nss(struct link_sta_info *link_sta); ++void ieee80211_sta_init_nss(struct link_sta_info *link_sta); + enum ieee80211_sta_rx_bandwidth + ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width); + enum nl80211_chan_width +--- a/net/mac80211/rate.c ++++ b/net/mac80211/rate.c +@@ -37,7 +37,7 @@ void rate_control_rate_init(struct sta_i + struct ieee80211_supported_band *sband; + struct ieee80211_chanctx_conf *chanctx_conf; + +- ieee80211_sta_set_rx_nss(&sta->deflink); ++ ieee80211_sta_init_nss(&sta->deflink); + + if (!ref) + return; +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -3,7 +3,7 @@ + * Copyright 2002-2005, Devicescape Software, Inc. + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright(c) 2015-2017 Intel Deutschland GmbH +- * Copyright(c) 2020-2022 Intel Corporation ++ * Copyright(c) 2020-2024 Intel Corporation + */ + + #ifndef STA_INFO_H +@@ -485,6 +485,8 @@ struct ieee80211_fragment_cache { + * same for non-MLD STA. This is used as key for searching link STA + * @link_id: Link ID uniquely identifying the link STA. This is 0 for non-MLD + * and set to the corresponding vif LinkId for MLD STA ++ * @op_mode_nss: NSS limit as set by operating mode notification, or 0 ++ * @capa_nss: NSS limit as determined by local and peer capabilities + * @link_hash_node: hash node for rhashtable + * @sta: Points to the STA info + * @gtk: group keys negotiated with this station, if any +@@ -520,6 +522,8 @@ struct link_sta_info { + u8 addr[ETH_ALEN]; + u8 link_id; + ++ u8 op_mode_nss, capa_nss; ++ + struct rhlist_head link_hash_node; + + struct sta_info *sta; +--- a/net/mac80211/vht.c ++++ b/net/mac80211/vht.c +@@ -4,7 +4,7 @@ + * + * Portions of this file + * Copyright(c) 2015 - 2016 Intel Deutschland GmbH +- * Copyright (C) 2018 - 2023 Intel Corporation ++ * Copyright (C) 2018 - 2024 Intel Corporation + */ + + #include +@@ -541,15 +541,11 @@ ieee80211_sta_cur_vht_bw(struct link_sta + return bw; + } + +-void ieee80211_sta_set_rx_nss(struct link_sta_info *link_sta) ++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 we received a notification already don't overwrite it */ +- if (link_sta->pub->rx_nss) +- return; +- + 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; +@@ -627,7 +623,15 @@ void ieee80211_sta_set_rx_nss(struct lin + 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); +- link_sta->pub->rx_nss = max_t(u8, 1, 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, +@@ -637,7 +641,7 @@ u32 __ieee80211_vht_handle_opmode(struct + enum ieee80211_sta_rx_bandwidth new_bw; + struct sta_opmode_info sta_opmode = {}; + u32 changed = 0; +- u8 nss, cur_nss; ++ u8 nss; + + /* ignore - no support for BF yet */ + if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF) +@@ -647,23 +651,17 @@ u32 __ieee80211_vht_handle_opmode(struct + nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT; + nss += 1; + +- if (link_sta->pub->rx_nss != nss) { +- cur_nss = link_sta->pub->rx_nss; +- /* Reset rx_nss and call ieee80211_sta_set_rx_nss() which +- * will set the same to max nss value calculated based on capability. +- */ +- link_sta->pub->rx_nss = 0; +- ieee80211_sta_set_rx_nss(link_sta); +- /* Do not allow an nss change to rx_nss greater than max_nss +- * negotiated and capped to APs capability during association. +- */ +- if (nss <= link_sta->pub->rx_nss) { +- link_sta->pub->rx_nss = nss; +- sta_opmode.rx_nss = nss; +- changed |= IEEE80211_RC_NSS_CHANGED; +- sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED; ++ if (link_sta->op_mode_nss != nss) { ++ if (nss <= link_sta->capa_nss) { ++ link_sta->op_mode_nss = nss; ++ ++ if (nss != link_sta->pub->rx_nss) { ++ link_sta->pub->rx_nss = nss; ++ changed |= IEEE80211_RC_NSS_CHANGED; ++ sta_opmode.rx_nss = link_sta->pub->rx_nss; ++ sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED; ++ } + } else { +- link_sta->pub->rx_nss = cur_nss; + pr_warn_ratelimited("Ignoring NSS change in VHT Operating Mode Notification from %pM with invalid nss %d", + link_sta->pub->addr, nss); + } -- 2.25.1