aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/rx.c11
-rw-r--r--net/mac80211/vht.c73
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);
1707enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta);
1707enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); 1708enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta);
1708void ieee80211_sta_set_rx_nss(struct sta_info *sta); 1709void ieee80211_sta_set_rx_nss(struct sta_info *sta);
1709u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, 1710u32 __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
272enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta) 272enum 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
291static enum ieee80211_sta_rx_bandwidth
292ieee80211_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
311enum 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