diff options
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/rx.c | 11 | ||||
-rw-r--r-- | net/mac80211/vht.c | 73 |
3 files changed, 47 insertions, 38 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index cc6e964d9837..4f45cab8b7f1 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1704,6 +1704,7 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
1704 | struct ieee80211_supported_band *sband, | 1704 | struct ieee80211_supported_band *sband, |
1705 | const struct ieee80211_vht_cap *vht_cap_ie, | 1705 | const struct ieee80211_vht_cap *vht_cap_ie, |
1706 | struct sta_info *sta); | 1706 | struct sta_info *sta); |
1707 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta); | ||
1707 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); | 1708 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); |
1708 | void ieee80211_sta_set_rx_nss(struct sta_info *sta); | 1709 | void ieee80211_sta_set_rx_nss(struct sta_info *sta); |
1709 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 1710 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 49c23bdf08bb..444ebff955c1 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2597,7 +2597,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2597 | case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { | 2597 | case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { |
2598 | struct ieee80211_supported_band *sband; | 2598 | struct ieee80211_supported_band *sband; |
2599 | u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; | 2599 | u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; |
2600 | enum ieee80211_sta_rx_bandwidth new_bw; | 2600 | enum ieee80211_sta_rx_bandwidth max_bw, new_bw; |
2601 | 2601 | ||
2602 | /* If it doesn't support 40 MHz it can't change ... */ | 2602 | /* If it doesn't support 40 MHz it can't change ... */ |
2603 | if (!(rx->sta->sta.ht_cap.cap & | 2603 | if (!(rx->sta->sta.ht_cap.cap & |
@@ -2605,13 +2605,18 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2605 | goto handled; | 2605 | goto handled; |
2606 | 2606 | ||
2607 | if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) | 2607 | if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) |
2608 | new_bw = IEEE80211_STA_RX_BW_20; | 2608 | max_bw = IEEE80211_STA_RX_BW_20; |
2609 | else | 2609 | else |
2610 | new_bw = ieee80211_sta_cur_vht_bw(rx->sta); | 2610 | max_bw = ieee80211_sta_cap_rx_bw(rx->sta); |
2611 | |||
2612 | /* set cur_max_bandwidth and recalc sta bw */ | ||
2613 | rx->sta->cur_max_bandwidth = max_bw; | ||
2614 | new_bw = ieee80211_sta_cur_vht_bw(rx->sta); | ||
2611 | 2615 | ||
2612 | if (rx->sta->sta.bandwidth == new_bw) | 2616 | if (rx->sta->sta.bandwidth == new_bw) |
2613 | goto handled; | 2617 | goto handled; |
2614 | 2618 | ||
2619 | rx->sta->sta.bandwidth = new_bw; | ||
2615 | sband = rx->local->hw.wiphy->bands[status->band]; | 2620 | sband = rx->local->hw.wiphy->bands[status->band]; |
2616 | 2621 | ||
2617 | rate_control_rate_update(local, sband, rx->sta, | 2622 | rate_control_rate_update(local, sband, rx->sta, |
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 | ||