aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorKalle Valo <kalle.valo@nokia.com>2008-12-18 16:35:13 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-12-19 15:23:57 -0500
commite0cb686ff879dc9ac045ad7258ec687088d4e450 (patch)
tree4792dc94d6a36be8367987b88b922157acf59808 /net
parentd10d0e5707fb7b8afa7e68a14d69e752604ee294 (diff)
mac80211: enable IEEE80211_CONF_PS only when associated
Also disable power save when disassociated. It makes no sense to have power save enabled while disassociated. iwlwifi seems to have this check in the driver, but it's better to do this in mac80211 instead. Signed-off-by: Kalle Valo <kalle.valo@nokia.com> Acked-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-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}