aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/mlme.c15
-rw-r--r--net/mac80211/wext.c32
3 files changed, 40 insertions, 8 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index a7dabaecfc7..18b91601770 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -688,6 +688,7 @@ struct ieee80211_local {
*/
int wifi_wme_noack_test;
unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
+ bool powersave;
#ifdef CONFIG_MAC80211_DEBUGFS
struct local_debugfsdentries {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1374b8c750a..dac8bd37dcf 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -744,6 +744,11 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
bss_info_changed |= BSS_CHANGED_BASIC_RATES;
ieee80211_bss_info_change_notify(sdata, bss_info_changed);
+ if (local->powersave) {
+ local->hw.conf.flags |= IEEE80211_CONF_PS;
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+ }
+
netif_tx_start_all_queues(sdata->dev);
netif_carrier_on(sdata->dev);
@@ -812,7 +817,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
- u32 changed = 0;
+ u32 changed = 0, config_changed = 0;
rcu_read_lock();
@@ -859,8 +864,14 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
local->hw.conf.ht.enabled = false;
local->oper_channel_type = NL80211_CHAN_NO_HT;
- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT);
+ config_changed |= IEEE80211_CONF_CHANGE_HT;
+
+ if (local->hw.conf.flags & IEEE80211_CONF_PS) {
+ local->hw.conf.flags &= ~IEEE80211_CONF_PS;
+ config_changed |= IEEE80211_CONF_CHANGE_PS;
+ }
+ ieee80211_hw_config(local, config_changed);
ieee80211_bss_info_change_notify(sdata, changed);
rcu_read_lock();
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 15428048d01..f6640d04715 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -830,25 +830,46 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
struct iw_param *wrq,
char *extra)
{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_conf *conf = &local->hw.conf;
+ int ret = 0;
+ bool ps;
+
+ if (sdata->vif.type != NL80211_IFTYPE_STATION)
+ return -EINVAL;
if (wrq->disabled) {
- conf->flags &= ~IEEE80211_CONF_PS;
- return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+ ps = false;
+ goto set;
}
switch (wrq->flags & IW_POWER_MODE) {
case IW_POWER_ON: /* If not specified */
case IW_POWER_MODE: /* If set all mask */
case IW_POWER_ALL_R: /* If explicitely state all */
- conf->flags |= IEEE80211_CONF_PS;
+ ps = true;
break;
default: /* Otherwise we don't support it */
return -EINVAL;
}
- return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+ if (ps == local->powersave)
+ return ret;
+
+set:
+ local->powersave = ps;
+
+ if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
+ if (local->powersave)
+ conf->flags |= IEEE80211_CONF_PS;
+ else
+ conf->flags &= ~IEEE80211_CONF_PS;
+
+ ret = ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+ }
+
+ return ret;
}
static int ieee80211_ioctl_giwpower(struct net_device *dev,
@@ -857,9 +878,8 @@ static int ieee80211_ioctl_giwpower(struct net_device *dev,
char *extra)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_conf *conf = &local->hw.conf;
- wrqu->power.disabled = !(conf->flags & IEEE80211_CONF_PS);
+ wrqu->power.disabled = !local->powersave;
return 0;
}