diff options
author | Johannes Berg <johannes.berg@intel.com> | 2011-12-16 09:28:57 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-12-19 14:40:22 -0500 |
commit | 1d8d3dec5fbba15864f25c734a7fda5703234091 (patch) | |
tree | 68eedf5dabed48c4d0bed8be4d2c05541b4f626c /net/mac80211/rx.c | |
parent | 645d35902c8f05a1b12fa838aa9052d8eeaf161e (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.c | 58 |
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 && |