diff options
author | Johannes Berg <johannes.berg@intel.com> | 2016-10-20 02:52:50 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2017-01-11 10:35:05 -0500 |
commit | d2941df8fbd9708035d66d889ada4d3d160170ce (patch) | |
tree | b12b6d2813a2361e7556d74c1e2d6b543a0817b8 | |
parent | 96aa2e7cf126773b16c6c19b7474a8a38d3c707e (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.c | 21 | ||||
-rw-r--r-- | net/mac80211/rx.c | 9 | ||||
-rw-r--r-- | net/mac80211/vht.c | 4 |
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 | ||
534 | void ieee80211_get_vht_mask_from_cap(__le16 vht_cap, | 536 | void ieee80211_get_vht_mask_from_cap(__le16 vht_cap, |