aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h5
-rw-r--r--net/mac80211/rx.c58
2 files changed, 62 insertions, 1 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5b5c8a7e26d7..2a7523edd9b5 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3502,9 +3502,12 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
3502 * 3502 *
3503 * @IEEE80211_RC_HT_CHANGED: The HT parameters of the operating channel have 3503 * @IEEE80211_RC_HT_CHANGED: The HT parameters of the operating channel have
3504 * changed, rate control algorithm can update its internal state if needed. 3504 * changed, rate control algorithm can update its internal state if needed.
3505 * @IEEE80211_RC_SMPS_CHANGED: The SMPS state of the station changed, the rate
3506 * control algorithm needs to adjust accordingly.
3505 */ 3507 */
3506enum rate_control_changed { 3508enum rate_control_changed {
3507 IEEE80211_RC_HT_CHANGED = BIT(0) 3509 IEEE80211_RC_HT_CHANGED = BIT(0),
3510 IEEE80211_RC_SMPS_CHANGED = BIT(1),
3508}; 3511};
3509 3512
3510/** 3513/**
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 2be5b7d69ad7..57832eb44f3e 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -28,6 +28,7 @@
28#include "wpa.h" 28#include "wpa.h"
29#include "tkip.h" 29#include "tkip.h"
30#include "wme.h" 30#include "wme.h"
31#include "rate.h"
31 32
32/* 33/*
33 * monitor mode reception 34 * monitor mode reception
@@ -2233,6 +2234,63 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2233 return RX_DROP_UNUSABLE; 2234 return RX_DROP_UNUSABLE;
2234 2235
2235 switch (mgmt->u.action.category) { 2236 switch (mgmt->u.action.category) {
2237 case WLAN_CATEGORY_HT:
2238 /* reject HT action frames from stations not supporting HT */
2239 if (!rx->sta->sta.ht_cap.ht_supported)
2240 goto invalid;
2241
2242 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
2243 sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
2244 sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
2245 sdata->vif.type != NL80211_IFTYPE_AP &&
2246 sdata->vif.type != NL80211_IFTYPE_ADHOC)
2247 break;
2248
2249 /* verify action & smps_control are present */
2250 if (len < IEEE80211_MIN_ACTION_SIZE + 2)
2251 goto invalid;
2252
2253 switch (mgmt->u.action.u.ht_smps.action) {
2254 case WLAN_HT_ACTION_SMPS: {
2255 struct ieee80211_supported_band *sband;
2256 u8 smps;
2257
2258 /* convert to HT capability */
2259 switch (mgmt->u.action.u.ht_smps.smps_control) {
2260 case WLAN_HT_SMPS_CONTROL_DISABLED:
2261 smps = WLAN_HT_CAP_SM_PS_DISABLED;
2262 break;
2263 case WLAN_HT_SMPS_CONTROL_STATIC:
2264 smps = WLAN_HT_CAP_SM_PS_STATIC;
2265 break;
2266 case WLAN_HT_SMPS_CONTROL_DYNAMIC:
2267 smps = WLAN_HT_CAP_SM_PS_DYNAMIC;
2268 break;
2269 default:
2270 goto invalid;
2271 }
2272 smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
2273
2274 /* if no change do nothing */
2275 if ((rx->sta->sta.ht_cap.cap &
2276 IEEE80211_HT_CAP_SM_PS) == smps)
2277 goto handled;
2278
2279 rx->sta->sta.ht_cap.cap &= ~IEEE80211_HT_CAP_SM_PS;
2280 rx->sta->sta.ht_cap.cap |= smps;
2281
2282 sband = rx->local->hw.wiphy->bands[status->band];
2283
2284 rate_control_rate_update(local, sband, rx->sta,
2285 IEEE80211_RC_SMPS_CHANGED,
2286 local->_oper_channel_type);
2287 goto handled;
2288 }
2289 default:
2290 goto invalid;
2291 }
2292
2293 break;
2236 case WLAN_CATEGORY_BACK: 2294 case WLAN_CATEGORY_BACK:
2237 if (sdata->vif.type != NL80211_IFTYPE_STATION && 2295 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
2238 sdata->vif.type != NL80211_IFTYPE_MESH_POINT && 2296 sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&