diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 49 |
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 | ||
1321 | int __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 | |||
1321 | static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | 1365 | static 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 | ||