diff options
author | Eliad Peller <eliad@wizery.com> | 2014-12-14 04:05:51 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-12-17 09:45:16 -0500 |
commit | 1c45c5ce324fec967dca5993f79b54769da410dc (patch) | |
tree | 0dc0d83ef40d736f205d1570aec856d6b6d2889f /net/mac80211/vht.c | |
parent | a5fee9cb6255b9bba5a977f92cb4807eafb89db0 (diff) |
mac80211: update sta bw on ht chanwidth action frame
Commit e1a0c6b ("mac80211: stop toggling IEEE80211_HT_CAP_SUP_WIDTH_20_40")
mistakenly removed the actual update of sta->sta.bandwidth.
Refactor ieee80211_sta_cur_vht_bw() into multiple functions
(calculate caps-bw and chandef-bw separately, and min them
with cur_max_bandwidth).
On ht chanwidth action frame set only cur_max_bandwidth
(according to the sta capabilities) and recalc the sta bw.
Signed-off-by: Eliad Peller <eliadx.peller@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/vht.c')
-rw-r--r-- | net/mac80211/vht.c | 73 |
1 files changed, 38 insertions, 35 deletions
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index bc9e8fc48785..85f9596da07b 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -269,51 +269,54 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
269 | sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta); | 269 | sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta); |
270 | } | 270 | } |
271 | 271 | ||
272 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta) | 272 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta) |
273 | { | 273 | { |
274 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 274 | struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap; |
275 | u32 cap = sta->sta.vht_cap.cap; | 275 | u32 cap_width; |
276 | enum ieee80211_sta_rx_bandwidth bw; | ||
277 | 276 | ||
278 | if (!sta->sta.vht_cap.vht_supported) { | 277 | if (!vht_cap->vht_supported) |
279 | bw = sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ? | 278 | return sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ? |
280 | IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20; | 279 | IEEE80211_STA_RX_BW_40 : |
281 | goto check_max; | 280 | IEEE80211_STA_RX_BW_20; |
282 | } | ||
283 | 281 | ||
284 | switch (sdata->vif.bss_conf.chandef.width) { | 282 | cap_width = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; |
285 | default: | 283 | |
286 | WARN_ON_ONCE(1); | 284 | if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ || |
287 | /* fall through */ | 285 | cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) |
286 | return IEEE80211_STA_RX_BW_160; | ||
287 | |||
288 | return IEEE80211_STA_RX_BW_80; | ||
289 | } | ||
290 | |||
291 | static enum ieee80211_sta_rx_bandwidth | ||
292 | ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width) | ||
293 | { | ||
294 | switch (width) { | ||
288 | case NL80211_CHAN_WIDTH_20_NOHT: | 295 | case NL80211_CHAN_WIDTH_20_NOHT: |
289 | case NL80211_CHAN_WIDTH_20: | 296 | case NL80211_CHAN_WIDTH_20: |
290 | bw = IEEE80211_STA_RX_BW_20; | 297 | return IEEE80211_STA_RX_BW_20; |
291 | break; | ||
292 | case NL80211_CHAN_WIDTH_40: | 298 | case NL80211_CHAN_WIDTH_40: |
293 | bw = sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ? | 299 | return IEEE80211_STA_RX_BW_40; |
294 | IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20; | 300 | case NL80211_CHAN_WIDTH_80: |
295 | break; | 301 | return IEEE80211_STA_RX_BW_80; |
296 | case NL80211_CHAN_WIDTH_160: | 302 | case NL80211_CHAN_WIDTH_160: |
297 | if ((cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) == | ||
298 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ) { | ||
299 | bw = IEEE80211_STA_RX_BW_160; | ||
300 | break; | ||
301 | } | ||
302 | /* fall through */ | ||
303 | case NL80211_CHAN_WIDTH_80P80: | 303 | case NL80211_CHAN_WIDTH_80P80: |
304 | if ((cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) == | 304 | return IEEE80211_STA_RX_BW_160; |
305 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) { | 305 | default: |
306 | bw = IEEE80211_STA_RX_BW_160; | 306 | WARN_ON_ONCE(1); |
307 | break; | 307 | return IEEE80211_STA_RX_BW_20; |
308 | } | ||
309 | /* fall through */ | ||
310 | case NL80211_CHAN_WIDTH_80: | ||
311 | bw = IEEE80211_STA_RX_BW_80; | ||
312 | } | 308 | } |
309 | } | ||
310 | |||
311 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta) | ||
312 | { | ||
313 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
314 | enum ieee80211_sta_rx_bandwidth bw; | ||
315 | |||
316 | bw = ieee80211_chan_width_to_rx_bw(sdata->vif.bss_conf.chandef.width); | ||
317 | bw = min(bw, ieee80211_sta_cap_rx_bw(sta)); | ||
318 | bw = min(bw, sta->cur_max_bandwidth); | ||
313 | 319 | ||
314 | check_max: | ||
315 | if (bw > sta->cur_max_bandwidth) | ||
316 | bw = sta->cur_max_bandwidth; | ||
317 | return bw; | 320 | return bw; |
318 | } | 321 | } |
319 | 322 | ||