Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2900bcc1 authored by Ilan Peer's avatar Ilan Peer Committed by Greg Kroah-Hartman
Browse files

mac80211: Fix station bandwidth setting after channel switch



[ Upstream commit 0007e94355fdb71a1cf5dba0754155cba08f0666 ]

When performing a channel switch flow for a managed interface, the
flow did not update the bandwidth of the AP station and the rate
scale algorithm. In case of a channel width downgrade, this would
result with the rate scale algorithm using a bandwidth that does not
match the interface channel configuration.

Fix this by updating the AP station bandwidth and rate scaling algorithm
before the actual channel change in case of a bandwidth downgrade, or
after the actual channel change in case of a bandwidth upgrade.

Signed-off-by: default avatarIlan Peer <ilan.peer@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarSasha Levin <alexander.levin@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 27272872
Loading
Loading
Loading
Loading
+53 −0
Original line number Original line Diff line number Diff line
@@ -989,6 +989,10 @@ static void ieee80211_chswitch_work(struct work_struct *work)
	 */
	 */


	if (sdata->reserved_chanctx) {
	if (sdata->reserved_chanctx) {
		struct ieee80211_supported_band *sband = NULL;
		struct sta_info *mgd_sta = NULL;
		enum ieee80211_sta_rx_bandwidth bw = IEEE80211_STA_RX_BW_20;

		/*
		/*
		 * with multi-vif csa driver may call ieee80211_csa_finish()
		 * with multi-vif csa driver may call ieee80211_csa_finish()
		 * many times while waiting for other interfaces to use their
		 * many times while waiting for other interfaces to use their
@@ -997,6 +1001,48 @@ static void ieee80211_chswitch_work(struct work_struct *work)
		if (sdata->reserved_ready)
		if (sdata->reserved_ready)
			goto out;
			goto out;


		if (sdata->vif.bss_conf.chandef.width !=
		    sdata->csa_chandef.width) {
			/*
			 * For managed interface, we need to also update the AP
			 * station bandwidth and align the rate scale algorithm
			 * on the bandwidth change. Here we only consider the
			 * bandwidth of the new channel definition (as channel
			 * switch flow does not have the full HT/VHT/HE
			 * information), assuming that if additional changes are
			 * required they would be done as part of the processing
			 * of the next beacon from the AP.
			 */
			switch (sdata->csa_chandef.width) {
			case NL80211_CHAN_WIDTH_20_NOHT:
			case NL80211_CHAN_WIDTH_20:
			default:
				bw = IEEE80211_STA_RX_BW_20;
				break;
			case NL80211_CHAN_WIDTH_40:
				bw = IEEE80211_STA_RX_BW_40;
				break;
			case NL80211_CHAN_WIDTH_80:
				bw = IEEE80211_STA_RX_BW_80;
				break;
			case NL80211_CHAN_WIDTH_80P80:
			case NL80211_CHAN_WIDTH_160:
				bw = IEEE80211_STA_RX_BW_160;
				break;
			}

			mgd_sta = sta_info_get(sdata, ifmgd->bssid);
			sband =
				local->hw.wiphy->bands[sdata->csa_chandef.chan->band];
		}

		if (sdata->vif.bss_conf.chandef.width >
		    sdata->csa_chandef.width) {
			mgd_sta->sta.bandwidth = bw;
			rate_control_rate_update(local, sband, mgd_sta,
						 IEEE80211_RC_BW_CHANGED);
		}

		ret = ieee80211_vif_use_reserved_context(sdata);
		ret = ieee80211_vif_use_reserved_context(sdata);
		if (ret) {
		if (ret) {
			sdata_info(sdata,
			sdata_info(sdata,
@@ -1007,6 +1053,13 @@ static void ieee80211_chswitch_work(struct work_struct *work)
			goto out;
			goto out;
		}
		}


		if (sdata->vif.bss_conf.chandef.width <
		    sdata->csa_chandef.width) {
			mgd_sta->sta.bandwidth = bw;
			rate_control_rate_update(local, sband, mgd_sta,
						 IEEE80211_RC_BW_CHANGED);
		}

		goto out;
		goto out;
	}
	}