Commit e0cb686ff879dc9ac045ad7258ec687088d4e450
Committed by
John W. Linville
1 parent
d10d0e5707
Exists in
master
and in
7 other branches
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>
Showing 3 changed files with 40 additions and 8 deletions Side-by-side Diff
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
... | ... | @@ -744,6 +744,11 @@ |
744 | 744 | bss_info_changed |= BSS_CHANGED_BASIC_RATES; |
745 | 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 | 752 | netif_tx_start_all_queues(sdata->dev); |
748 | 753 | netif_carrier_on(sdata->dev); |
749 | 754 | |
... | ... | @@ -812,7 +817,7 @@ |
812 | 817 | { |
813 | 818 | struct ieee80211_local *local = sdata->local; |
814 | 819 | struct sta_info *sta; |
815 | - u32 changed = 0; | |
820 | + u32 changed = 0, config_changed = 0; | |
816 | 821 | |
817 | 822 | rcu_read_lock(); |
818 | 823 | |
819 | 824 | |
... | ... | @@ -859,8 +864,14 @@ |
859 | 864 | |
860 | 865 | local->hw.conf.ht.enabled = false; |
861 | 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; | |
863 | 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 | + } | |
873 | + | |
874 | + ieee80211_hw_config(local, config_changed); | |
864 | 875 | ieee80211_bss_info_change_notify(sdata, changed); |
865 | 876 | |
866 | 877 | rcu_read_lock(); |
net/mac80211/wext.c
... | ... | @@ -830,25 +830,46 @@ |
830 | 830 | struct iw_param *wrq, |
831 | 831 | char *extra) |
832 | 832 | { |
833 | + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | |
833 | 834 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
834 | 835 | struct ieee80211_conf *conf = &local->hw.conf; |
836 | + int ret = 0; | |
837 | + bool ps; | |
835 | 838 | |
839 | + if (sdata->vif.type != NL80211_IFTYPE_STATION) | |
840 | + return -EINVAL; | |
841 | + | |
836 | 842 | if (wrq->disabled) { |
837 | - conf->flags &= ~IEEE80211_CONF_PS; | |
838 | - return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | |
843 | + ps = false; | |
844 | + goto set; | |
839 | 845 | } |
840 | 846 | |
841 | 847 | switch (wrq->flags & IW_POWER_MODE) { |
842 | 848 | case IW_POWER_ON: /* If not specified */ |
843 | 849 | case IW_POWER_MODE: /* If set all mask */ |
844 | 850 | case IW_POWER_ALL_R: /* If explicitely state all */ |
845 | - conf->flags |= IEEE80211_CONF_PS; | |
851 | + ps = true; | |
846 | 852 | break; |
847 | 853 | default: /* Otherwise we don't support it */ |
848 | 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 | + | |
860 | +set: | |
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 | |
854 | 875 | static int ieee80211_ioctl_giwpower(struct net_device *dev, |
855 | 876 | |
... | ... | @@ -857,9 +878,8 @@ |
857 | 878 | char *extra) |
858 | 879 | { |
859 | 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 | 884 | return 0; |
865 | 885 | } |