diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2013-10-01 16:45:43 +0300 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-10-28 15:05:11 +0100 |
commit | 687da132234feb70748df04a007bc1820f392254 (patch) | |
tree | 6255afe03b39518c2f83251fd0dd0afed647dd44 /net/mac80211/util.c | |
parent | 7ec7c4a9a686c608315739ab6a2b0527a240883c (diff) |
mac80211: implement SMPS for AP
When the driver requests to move to STATIC or DYNAMIC SMPS,
we send an action frame to each associated station and
reconfigure the channel context / driver.
Of course, non-MIMO stations are ignored.
The beacon isn't updated. The association response will
include the original capabilities. Stations that associate
while in non-OFF SMPS mode will get an action frame right
after association to inform them about our current state.
Note that we wait until the end of the EAPOL. Sending an
action frame before the EAPOL is finished can be an issue
for a few clients. Clients aren't likely to send EAPOL
frames in MIMO anyway.
When the SMPS configuration gets more permissive (e.g.
STATIC -> OFF), we don't wake up stations that are asleep
We remember that they don't know about the change and send
the action frame when they wake up.
When the SMPS configuration gets more restrictive (e.g.
OFF -> STATIC), we set the TIM bit for every sleeping STA.
uAPSD stations might send MIMO until they poll the action
frame, but this is for a short period of time.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
[fix vht streams loop, initialisation]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 550a6880625d..b763e4ccaf5e 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -2353,3 +2353,28 @@ u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c) return ret; } + +/* + * Returns true if smps_mode_new is strictly more restrictive than + * smps_mode_old. + */ +bool ieee80211_smps_is_restrictive(enum ieee80211_smps_mode smps_mode_old, + enum ieee80211_smps_mode smps_mode_new) +{ + if (WARN_ON_ONCE(smps_mode_old == IEEE80211_SMPS_AUTOMATIC || + smps_mode_new == IEEE80211_SMPS_AUTOMATIC)) + return false; + + switch (smps_mode_old) { + case IEEE80211_SMPS_STATIC: + return false; + case IEEE80211_SMPS_DYNAMIC: + return smps_mode_new == IEEE80211_SMPS_STATIC; + case IEEE80211_SMPS_OFF: + return smps_mode_new != IEEE80211_SMPS_OFF; + default: + WARN_ON(1); + } + + return false; +} |