aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/mlme.c26
-rw-r--r--net/mac80211/rx.c3
-rw-r--r--net/mac80211/util.c6
-rw-r--r--net/mac80211/vht.c6
5 files changed, 38 insertions, 6 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4947c91c6c86..892bac64a189 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1197,6 +1197,7 @@ struct ieee802_11_elems {
1197 u8 *pwr_constr_elem; 1197 u8 *pwr_constr_elem;
1198 u8 *quiet_elem; /* first quite element */ 1198 u8 *quiet_elem; /* first quite element */
1199 u8 *timeout_int; 1199 u8 *timeout_int;
1200 u8 *opmode_notif;
1200 1201
1201 /* length of them, respectively */ 1202 /* length of them, respectively */
1202 u8 ssid_len; 1203 u8 ssid_len;
@@ -1435,7 +1436,7 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta);
1435void ieee80211_sta_set_rx_nss(struct sta_info *sta); 1436void ieee80211_sta_set_rx_nss(struct sta_info *sta);
1436void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, 1437void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
1437 struct sta_info *sta, u8 opmode, 1438 struct sta_info *sta, u8 opmode,
1438 enum ieee80211_band band); 1439 enum ieee80211_band band, bool nss_only);
1439 1440
1440/* Spectrum management */ 1441/* Spectrum management */
1441void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, 1442void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index e6da6bf8cc27..f2c6f7794f35 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2217,6 +2217,21 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2217 elems.ht_operation, 2217 elems.ht_operation,
2218 cbss->bssid, false); 2218 cbss->bssid, false);
2219 2219
2220 /*
2221 * If an operating mode notification IE is present, override the
2222 * NSS calculation (that would be done in rate_control_rate_init())
2223 * and use the # of streams from that element.
2224 */
2225 if (elems.opmode_notif &&
2226 !(*elems.opmode_notif & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF)) {
2227 u8 nss;
2228
2229 nss = *elems.opmode_notif & IEEE80211_OPMODE_NOTIF_RX_NSS_MASK;
2230 nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT;
2231 nss += 1;
2232 sta->sta.rx_nss = nss;
2233 }
2234
2220 rate_control_rate_init(sta); 2235 rate_control_rate_init(sta);
2221 2236
2222 if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) 2237 if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED)
@@ -2489,6 +2504,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2489 struct ieee80211_local *local = sdata->local; 2504 struct ieee80211_local *local = sdata->local;
2490 struct ieee80211_chanctx_conf *chanctx_conf; 2505 struct ieee80211_chanctx_conf *chanctx_conf;
2491 struct ieee80211_channel *chan; 2506 struct ieee80211_channel *chan;
2507 struct sta_info *sta;
2492 u32 changed = 0; 2508 u32 changed = 0;
2493 bool erp_valid; 2509 bool erp_valid;
2494 u8 erp_value = 0; 2510 u8 erp_value = 0;
@@ -2728,14 +2744,18 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2728 le16_to_cpu(mgmt->u.beacon.capab_info), 2744 le16_to_cpu(mgmt->u.beacon.capab_info),
2729 erp_valid, erp_value); 2745 erp_valid, erp_value);
2730 2746
2731
2732 mutex_lock(&local->sta_mtx); 2747 mutex_lock(&local->sta_mtx);
2748 sta = sta_info_get(sdata, bssid);
2749
2733 if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param && 2750 if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param &&
2734 !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) 2751 !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
2735 changed |= ieee80211_config_ht_tx(sdata, 2752 changed |= ieee80211_config_ht_tx(sdata, sta,
2736 sta_info_get(sdata, bssid),
2737 elems.ht_operation, 2753 elems.ht_operation,
2738 bssid, true); 2754 bssid, true);
2755
2756 if (sta && elems.opmode_notif)
2757 ieee80211_vht_handle_opmode(sdata, sta, *elems.opmode_notif,
2758 rx_status->band, true);
2739 mutex_unlock(&local->sta_mtx); 2759 mutex_unlock(&local->sta_mtx);
2740 2760
2741 if (elems.country_elem && elems.pwr_constr_elem && 2761 if (elems.country_elem && elems.pwr_constr_elem &&
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 1617e0bd4ca6..30f1ba6de8f3 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2459,7 +2459,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2459 opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode; 2459 opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
2460 2460
2461 ieee80211_vht_handle_opmode(rx->sdata, rx->sta, 2461 ieee80211_vht_handle_opmode(rx->sdata, rx->sta,
2462 opmode, status->band); 2462 opmode, status->band,
2463 false);
2463 goto handled; 2464 goto handled;
2464 } 2465 }
2465 default: 2466 default:
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index b231bc2ed740..e24ff38606a9 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -787,6 +787,12 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
787 else 787 else
788 elem_parse_failed = true; 788 elem_parse_failed = true;
789 break; 789 break;
790 case WLAN_EID_OPMODE_NOTIF:
791 if (elen > 0)
792 elems->opmode_notif = pos;
793 else
794 elem_parse_failed = true;
795 break;
790 case WLAN_EID_MESH_ID: 796 case WLAN_EID_MESH_ID:
791 elems->mesh_id = pos; 797 elems->mesh_id = pos;
792 elems->mesh_id_len = elen; 798 elems->mesh_id_len = elen;
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index 0951f74e7ff5..a9549fcc5a04 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -141,7 +141,7 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta)
141 141
142void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, 142void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
143 struct sta_info *sta, u8 opmode, 143 struct sta_info *sta, u8 opmode,
144 enum ieee80211_band band) 144 enum ieee80211_band band, bool nss_only)
145{ 145{
146 struct ieee80211_local *local = sdata->local; 146 struct ieee80211_local *local = sdata->local;
147 struct ieee80211_supported_band *sband; 147 struct ieee80211_supported_band *sband;
@@ -164,6 +164,9 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
164 changed |= IEEE80211_RC_NSS_CHANGED; 164 changed |= IEEE80211_RC_NSS_CHANGED;
165 } 165 }
166 166
167 if (nss_only)
168 goto change;
169
167 switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) { 170 switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) {
168 case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: 171 case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ:
169 sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_20; 172 sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_20;
@@ -185,6 +188,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
185 changed |= IEEE80211_RC_NSS_CHANGED; 188 changed |= IEEE80211_RC_NSS_CHANGED;
186 } 189 }
187 190
191 change:
188 if (changed) 192 if (changed)
189 rate_control_rate_update(local, sband, sta, changed); 193 rate_control_rate_update(local, sband, sta, changed);
190} 194}