aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-12-16 09:28:57 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-12-19 14:40:22 -0500
commit1d8d3dec5fbba15864f25c734a7fda5703234091 (patch)
tree68eedf5dabed48c4d0bed8be4d2c05541b4f626c /net/mac80211/rx.c
parent645d35902c8f05a1b12fa838aa9052d8eeaf161e (diff)
mac80211: handle SMPS action frames
When a peer changes SMPS state we should update rate control so it doesn't have to detect it by itself. It can't detect "dynamic" mode anyway since that just requires rts-cts handshaking. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c58
1 files changed, 58 insertions, 0 deletions
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 &&