aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2016-10-20 02:52:50 -0400
committerJohannes Berg <johannes.berg@intel.com>2017-01-11 10:35:05 -0500
commitd2941df8fbd9708035d66d889ada4d3d160170ce (patch)
treeb12b6d2813a2361e7556d74c1e2d6b543a0817b8
parent96aa2e7cf126773b16c6c19b7474a8a38d3c707e (diff)
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: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/iface.c21
-rw-r--r--net/mac80211/rx.c9
-rw-r--r--net/mac80211/vht.c4
3 files changed, 25 insertions, 9 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 41497b670e2b..d37ae7dc114b 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -6,6 +6,7 @@
6 * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> 6 * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
7 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> 7 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
8 * Copyright 2013-2014 Intel Mobile Communications GmbH 8 * Copyright 2013-2014 Intel Mobile Communications GmbH
9 * Copyright (c) 2016 Intel Deutschland GmbH
9 * 10 *
10 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 12 * 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)
1295 } else if (ieee80211_is_action(mgmt->frame_control) && 1296 } else if (ieee80211_is_action(mgmt->frame_control) &&
1296 mgmt->u.action.category == WLAN_CATEGORY_VHT) { 1297 mgmt->u.action.category == WLAN_CATEGORY_VHT) {
1297 switch (mgmt->u.action.u.vht_group_notif.action_code) { 1298 switch (mgmt->u.action.u.vht_group_notif.action_code) {
1299 case WLAN_VHT_ACTION_OPMODE_NOTIF: {
1300 struct ieee80211_rx_status *status;
1301 enum nl80211_band band;
1302 u8 opmode;
1303
1304 status = IEEE80211_SKB_RXCB(skb);
1305 band = status->band;
1306 opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
1307
1308 mutex_lock(&local->sta_mtx);
1309 sta = sta_info_get_bss(sdata, mgmt->sa);
1310
1311 if (sta)
1312 ieee80211_vht_handle_opmode(sdata, sta,
1313 opmode,
1314 band);
1315
1316 mutex_unlock(&local->sta_mtx);
1317 break;
1318 }
1298 case WLAN_VHT_ACTION_GROUPID_MGMT: 1319 case WLAN_VHT_ACTION_GROUPID_MGMT:
1299 ieee80211_process_mu_groups(sdata, mgmt); 1320 ieee80211_process_mu_groups(sdata, mgmt);
1300 break; 1321 break;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index c87e61358b77..3090dd4342f6 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2881,17 +2881,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2881 2881
2882 switch (mgmt->u.action.u.vht_opmode_notif.action_code) { 2882 switch (mgmt->u.action.u.vht_opmode_notif.action_code) {
2883 case WLAN_VHT_ACTION_OPMODE_NOTIF: { 2883 case WLAN_VHT_ACTION_OPMODE_NOTIF: {
2884 u8 opmode;
2885
2886 /* verify opmode is present */ 2884 /* verify opmode is present */
2887 if (len < IEEE80211_MIN_ACTION_SIZE + 2) 2885 if (len < IEEE80211_MIN_ACTION_SIZE + 2)
2888 goto invalid; 2886 goto invalid;
2889 2887 goto queue;
2890 opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
2891
2892 ieee80211_vht_handle_opmode(rx->sdata, rx->sta,
2893 opmode, status->band);
2894 goto handled;
2895 } 2888 }
2896 case WLAN_VHT_ACTION_GROUPID_MGMT: { 2889 case WLAN_VHT_ACTION_GROUPID_MGMT: {
2897 if (len < IEEE80211_MIN_ACTION_SIZE + 25) 2890 if (len < IEEE80211_MIN_ACTION_SIZE + 25)
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index 6832bf6ab69f..43e45bb660bc 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -527,8 +527,10 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
527 527
528 u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band); 528 u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band);
529 529
530 if (changed > 0) 530 if (changed > 0) {
531 ieee80211_recalc_min_chandef(sdata);
531 rate_control_rate_update(local, sband, sta, changed); 532 rate_control_rate_update(local, sband, sta, changed);
533 }
532} 534}
533 535
534void ieee80211_get_vht_mask_from_cap(__le16 vht_cap, 536void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,