Blob Blame History Raw
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,