aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-12-01 07:37:02 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-12-22 13:31:16 -0500
commit0f78231bffb868a30e8533aace142213266bb811 (patch)
tree317f65dc6d89e9a89ad83f94fadd780dd1e0ca83 /net/mac80211/cfg.c
parent18974b5b0b5e758d416c550553b143e5c8038281 (diff)
mac80211: enable spatial multiplexing powersave
Enable spatial multiplexing in mac80211 by telling the driver what to do and, where necessary, sending action frames to the AP to update the requested SMPS mode. Also includes a trivial implementation for hwsim that just logs the requested mode. For now, the userspace interface is in debugfs only, and let you toggle the requested mode at any time. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index fcfa1bf776a7..8c35418d1c96 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1318,6 +1318,50 @@ static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
1318} 1318}
1319#endif 1319#endif
1320 1320
1321int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
1322 enum ieee80211_smps_mode smps_mode)
1323{
1324 const u8 *ap;
1325 enum ieee80211_smps_mode old_req;
1326 int err;
1327
1328 old_req = sdata->u.mgd.req_smps;
1329 sdata->u.mgd.req_smps = smps_mode;
1330
1331 if (old_req == smps_mode &&
1332 smps_mode != IEEE80211_SMPS_AUTOMATIC)
1333 return 0;
1334
1335 /*
1336 * If not associated, or current association is not an HT
1337 * association, there's no need to send an action frame.
1338 */
1339 if (!sdata->u.mgd.associated ||
1340 sdata->local->oper_channel_type == NL80211_CHAN_NO_HT) {
1341 mutex_lock(&sdata->local->iflist_mtx);
1342 ieee80211_recalc_smps(sdata->local, sdata);
1343 mutex_unlock(&sdata->local->iflist_mtx);
1344 return 0;
1345 }
1346
1347 ap = sdata->u.mgd.associated->cbss.bssid;
1348
1349 if (smps_mode == IEEE80211_SMPS_AUTOMATIC) {
1350 if (sdata->u.mgd.powersave)
1351 smps_mode = IEEE80211_SMPS_DYNAMIC;
1352 else
1353 smps_mode = IEEE80211_SMPS_OFF;
1354 }
1355
1356 /* send SM PS frame to AP */
1357 err = ieee80211_send_smps_action(sdata, smps_mode,
1358 ap, ap);
1359 if (err)
1360 sdata->u.mgd.req_smps = old_req;
1361
1362 return err;
1363}
1364
1321static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, 1365static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
1322 bool enabled, int timeout) 1366 bool enabled, int timeout)
1323{ 1367{
@@ -1335,6 +1379,11 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
1335 sdata->u.mgd.powersave = enabled; 1379 sdata->u.mgd.powersave = enabled;
1336 conf->dynamic_ps_timeout = timeout; 1380 conf->dynamic_ps_timeout = timeout;
1337 1381
1382 /* no change, but if automatic follow powersave */
1383 mutex_lock(&sdata->u.mgd.mtx);
1384 __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps);
1385 mutex_unlock(&sdata->u.mgd.mtx);
1386
1338 if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) 1387 if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
1339 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); 1388 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
1340 1389