From 175ad2ec89feb8c01f87be64882af67481b1b1f5 Mon Sep 17 00:00:00 2001
From: Johannes Berg <johannes.berg@intel.com>
Date: Wed, 13 Jul 2022 18:08:03 +0200
Subject: [PATCH] wifi: mac80211: limit A-MSDU subframes for client too
Git-commit: 175ad2ec89feb8c01f87be64882af67481b1b1f5
Patch-mainline: v6.0-rc1
References: git-fixes
In AP/mesh where the stations are added by userspace, we
limit the number of A-MSDU subframes according to the
extended capabilities.
Refactor the code and extend that also to client-side.
Fixes: 506bcfa8abeb ("mac80211: limit the A-MSDU Tx based on peer's capabilities")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Acked-by: Takashi Iwai <tiwai@suse.de>
---
net/mac80211/cfg.c | 29 ++---------------------------
net/mac80211/mlme.c | 3 +++
net/mac80211/sta_info.c | 23 +++++++++++++++++++++++
net/mac80211/sta_info.h | 4 ++++
4 files changed, 32 insertions(+), 27 deletions(-)
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1592,33 +1592,8 @@ static int sta_apply_parameters(struct i
sta->sta.max_sp = params->max_sp;
}
- /* The sender might not have sent the last bit, consider it to be 0 */
- if (params->ext_capab_len >= 8) {
- u8 val = (params->ext_capab[7] &
- WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB) >> 7;
-
- /* we did get all the bits, take the MSB as well */
- if (params->ext_capab_len >= 9) {
- u8 val_msb = params->ext_capab[8] &
- WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB;
- val_msb <<= 1;
- val |= val_msb;
- }
-
- switch (val) {
- case 1:
- sta->sta.max_amsdu_subframes = 32;
- break;
- case 2:
- sta->sta.max_amsdu_subframes = 16;
- break;
- case 3:
- sta->sta.max_amsdu_subframes = 8;
- break;
- default:
- sta->sta.max_amsdu_subframes = 0;
- }
- }
+ ieee80211_sta_set_max_amsdu_subframes(sta, params->ext_capab,
+ params->ext_capab_len);
/*
* cfg80211 validates this (1-2007) and allows setting the AID
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3575,6 +3575,9 @@ static bool ieee80211_assoc_success(stru
sta->sta.mfp = false;
}
+ ieee80211_sta_set_max_amsdu_subframes(sta, elems->ext_capab,
+ elems->ext_capab_len);
+
sta->sta.wme = (elems->wmm_param || elems->s1g_capab) &&
local->hw.queues >= IEEE80211_NUM_ACS;
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2597,3 +2597,26 @@ void ieee80211_sta_set_expected_throughp
sta_update_codel_params(sta, thr);
}
+
+void ieee80211_sta_set_max_amsdu_subframes(struct sta_info *sta,
+ const u8 *ext_capab,
+ unsigned int ext_capab_len)
+{
+ u8 val;
+
+ sta->sta.max_amsdu_subframes = 0;
+
+ if (ext_capab_len < 8)
+ return;
+
+ /* The sender might not have sent the last bit, consider it to be 0 */
+ val = u8_get_bits(ext_capab[7], WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB);
+
+ /* we did get all the bits, take the MSB as well */
+ if (ext_capab_len >= 9)
+ val |= u8_get_bits(ext_capab[8],
+ WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB) << 1;
+
+ if (val)
+ sta->sta.max_amsdu_subframes = 4 << val;
+}
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -863,6 +863,10 @@ void ieee80211_sta_ps_deliver_uapsd(stru
unsigned long ieee80211_sta_last_active(struct sta_info *sta);
+void ieee80211_sta_set_max_amsdu_subframes(struct sta_info *sta,
+ const u8 *ext_capab,
+ unsigned int ext_capab_len);
+
enum sta_stats_type {
STA_STATS_RATE_TYPE_INVALID = 0,
STA_STATS_RATE_TYPE_LEGACY,