Commit 175ad2ec authored by Johannes Berg's avatar Johannes Berg
Browse files

wifi: mac80211: limit A-MSDU subframes for client too



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: 506bcfa8 ("mac80211: limit the A-MSDU Tx based on peer's capabilities")
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 5d3a341c
Loading
Loading
Loading
Loading
+2 −27
Original line number Diff line number Diff line
@@ -1776,33 +1776,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,
		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
+3 −0
Original line number Diff line number Diff line
@@ -4488,6 +4488,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
		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;

+23 −0
Original line number Diff line number Diff line
@@ -2761,3 +2761,26 @@ void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id)

	sta_remove_link(sta, link_id, true);
}

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;
}
+4 −0
Original line number Diff line number Diff line
@@ -910,6 +910,10 @@ void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta);

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,