mac80211: enable IEEE80211_CONF_PS only when associated
[safe/jmp/linux-2.6] / net / mac80211 / wext.c
index 1542804..f6640d0 100644 (file)
@@ -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;
 }