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

Commit d2941df8 authored by Johannes Berg's avatar Johannes Berg
Browse files

mac80211: recalculate min channel width on VHT opmode changes



When an associated station changes its VHT operating mode this
can/will affect the bandwidth it's using, and consequently we
must recalculate the minimum bandwidth we need to use. Failure
to do so can lead to one of two scenarios:
 1) we use a too high bandwidth, this is benign
 2) we use a too narrow bandwidth, causing rate control and
    actual PHY configuration to be out of sync, which can in
    turn cause problems/crashes

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 96aa2e7c
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
 * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
 * Copyright 2013-2014  Intel Mobile Communications GmbH
 * Copyright (c) 2016        Intel Deutschland GmbH
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
@@ -1295,6 +1296,26 @@ static void ieee80211_iface_work(struct work_struct *work)
		} else if (ieee80211_is_action(mgmt->frame_control) &&
			   mgmt->u.action.category == WLAN_CATEGORY_VHT) {
			switch (mgmt->u.action.u.vht_group_notif.action_code) {
			case WLAN_VHT_ACTION_OPMODE_NOTIF: {
				struct ieee80211_rx_status *status;
				enum nl80211_band band;
				u8 opmode;

				status = IEEE80211_SKB_RXCB(skb);
				band = status->band;
				opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;

				mutex_lock(&local->sta_mtx);
				sta = sta_info_get_bss(sdata, mgmt->sa);

				if (sta)
					ieee80211_vht_handle_opmode(sdata, sta,
								    opmode,
								    band);

				mutex_unlock(&local->sta_mtx);
				break;
			}
			case WLAN_VHT_ACTION_GROUPID_MGMT:
				ieee80211_process_mu_groups(sdata, mgmt);
				break;
+1 −8
Original line number Diff line number Diff line
@@ -2881,17 +2881,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)

		switch (mgmt->u.action.u.vht_opmode_notif.action_code) {
		case WLAN_VHT_ACTION_OPMODE_NOTIF: {
			u8 opmode;

			/* verify opmode is present */
			if (len < IEEE80211_MIN_ACTION_SIZE + 2)
				goto invalid;

			opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;

			ieee80211_vht_handle_opmode(rx->sdata, rx->sta,
						    opmode, status->band);
			goto handled;
			goto queue;
		}
		case WLAN_VHT_ACTION_GROUPID_MGMT: {
			if (len < IEEE80211_MIN_ACTION_SIZE + 25)
+3 −1
Original line number Diff line number Diff line
@@ -527,9 +527,11 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,

	u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band);

	if (changed > 0)
	if (changed > 0) {
		ieee80211_recalc_min_chandef(sdata);
		rate_control_rate_update(local, sband, sta, changed);
	}
}

void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
				     u16 vht_mask[NL80211_VHT_NSS_MAX])