summaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-02-07 16:24:55 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-02-15 03:41:34 -0500
commitbee7f58699a406a4210ba9e0367bae7ac666abd0 (patch)
tree9925ff46a41d09667fe797460b2d3ccb07fed4dd /net/mac80211/mlme.c
parent18942d3be0e0e67aa40550ce3266e48b51845d52 (diff)
mac80211: handle operating mode notif in beacon/assoc response
In beacons and association response frames an AP may include an operating mode notification element to advertise changes in the number of spatial streams it can receive. Handle this using the existing function that handles the action frame, but only handle NSS changes, not bandwidth changes which aren't allowed here. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c26
1 files changed, 23 insertions, 3 deletions
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 &&