aboutsummaryrefslogtreecommitdiffstats
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 a7dabaecfc72..18b91601770a 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -688,6 +688,7 @@ struct ieee80211_local {
688 */ 688 */
689 int wifi_wme_noack_test; 689 int wifi_wme_noack_test;
690 unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ 690 unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
691 bool powersave;
691 692
692#ifdef CONFIG_MAC80211_DEBUGFS 693#ifdef CONFIG_MAC80211_DEBUGFS
693 struct local_debugfsdentries { 694 struct local_debugfsdentries {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1374b8c750ab..dac8bd37dcf5 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,
744 bss_info_changed |= BSS_CHANGED_BASIC_RATES; 744 bss_info_changed |= BSS_CHANGED_BASIC_RATES;
745 ieee80211_bss_info_change_notify(sdata, bss_info_changed); 745 ieee80211_bss_info_change_notify(sdata, bss_info_changed);
746 746
747 if (local->powersave) {
748 local->hw.conf.flags |= IEEE80211_CONF_PS;
749 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
750 }
751
747 netif_tx_start_all_queues(sdata->dev); 752 netif_tx_start_all_queues(sdata->dev);
748 netif_carrier_on(sdata->dev); 753 netif_carrier_on(sdata->dev);
749 754
@@ -812,7 +817,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
812{ 817{
813 struct ieee80211_local *local = sdata->local; 818 struct ieee80211_local *local = sdata->local;
814 struct sta_info *sta; 819 struct sta_info *sta;
815 u32 changed = 0; 820 u32 changed = 0, config_changed = 0;
816 821
817 rcu_read_lock(); 822 rcu_read_lock();
818 823
@@ -859,8 +864,14 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
859 864
860 local->hw.conf.ht.enabled = false; 865 local->hw.conf.ht.enabled = false;
861 local->oper_channel_type = NL80211_CHAN_NO_HT; 866 local->oper_channel_type = NL80211_CHAN_NO_HT;
862 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); 867 config_changed |= IEEE80211_CONF_CHANGE_HT;
868
869 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
870 local->hw.conf.flags &= ~IEEE80211_CONF_PS;
871 config_changed |= IEEE80211_CONF_CHANGE_PS;
872 }
863 873
874 ieee80211_hw_config(local, config_changed);
864 ieee80211_bss_info_change_notify(sdata, changed); 875 ieee80211_bss_info_change_notify(sdata, changed);
865 876
866 rcu_read_lock(); 877 rcu_read_lock();
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 15428048d01a..f6640d047157 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -830,25 +830,46 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev,
830 struct iw_param *wrq, 830 struct iw_param *wrq,
831 char *extra) 831 char *extra)
832{ 832{
833 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
833 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 834 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
834 struct ieee80211_conf *conf = &local->hw.conf; 835 struct ieee80211_conf *conf = &local->hw.conf;
836 int ret = 0;
837 bool ps;
838
839 if (sdata->vif.type != NL80211_IFTYPE_STATION)
840 return -EINVAL;
835 841
836 if (wrq->disabled) { 842 if (wrq->disabled) {
837 conf->flags &= ~IEEE80211_CONF_PS; 843 ps = false;
838 return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); 844 goto set;
839 } 845 }
840 846
841 switch (wrq->flags & IW_POWER_MODE) { 847 switch (wrq->flags & IW_POWER_MODE) {
842 case IW_POWER_ON: /* If not specified */ 848 case IW_POWER_ON: /* If not specified */
843 case IW_POWER_MODE: /* If set all mask */ 849 case IW_POWER_MODE: /* If set all mask */
844 case IW_POWER_ALL_R: /* If explicitely state all */ 850 case IW_POWER_ALL_R: /* If explicitely state all */
845 conf->flags |= IEEE80211_CONF_PS; 851 ps = true;
846 break; 852 break;
847 default: /* Otherwise we don't support it */ 853 default: /* Otherwise we don't support it */
848 return -EINVAL; 854 return -EINVAL;
849 } 855 }
850 856
851 return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); 857 if (ps == local->powersave)
858 return ret;
859
860set:
861 local->powersave = ps;
862
863 if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
864 if (local->powersave)
865 conf->flags |= IEEE80211_CONF_PS;
866 else
867 conf->flags &= ~IEEE80211_CONF_PS;
868
869 ret = ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
870 }
871
872 return ret;
852} 873}
853 874
854static int ieee80211_ioctl_giwpower(struct net_device *dev, 875static int ieee80211_ioctl_giwpower(struct net_device *dev,
@@ -857,9 +878,8 @@ static int ieee80211_ioctl_giwpower(struct net_device *dev,
857 char *extra) 878 char *extra)
858{ 879{
859 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 880 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
860 struct ieee80211_conf *conf = &local->hw.conf;
861 881
862 wrqu->power.disabled = !(conf->flags & IEEE80211_CONF_PS); 882 wrqu->power.disabled = !local->powersave;
863 883
864 return 0; 884 return 0;
865} 885}