Commit e0cb686ff879dc9ac045ad7258ec687088d4e450

Authored by Kalle Valo
Committed by John W. Linville
1 parent d10d0e5707

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
... ... @@ -688,6 +688,7 @@
688 688 */
689 689 int wifi_wme_noack_test;
690 690 unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
  691 + bool powersave;
691 692  
692 693 #ifdef CONFIG_MAC80211_DEBUGFS
693 694 struct local_debugfsdentries {
... ... @@ -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();
... ... @@ -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 }