Merge branch 'master' of git://git.infradead.org/users/linville/wireless-next into...
[pandora-kernel.git] / net / mac80211 / cfg.c
index 119a573..ebd7fb1 100644 (file)
@@ -63,7 +63,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
 
        if (type == NL80211_IFTYPE_AP_VLAN &&
            params && params->use_4addr == 0)
-               rcu_assign_pointer(sdata->u.vlan.sta, NULL);
+               RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
        else if (type == NL80211_IFTYPE_STATION &&
                 params && params->use_4addr >= 0)
                sdata->u.mgd.use_4addr = params->use_4addr;
@@ -344,7 +344,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
                        STATION_INFO_RX_BITRATE |
                        STATION_INFO_RX_DROP_MISC |
                        STATION_INFO_BSS_PARAM |
-                       STATION_INFO_CONNECTED_TIME;
+                       STATION_INFO_CONNECTED_TIME |
+                       STATION_INFO_STA_FLAGS;
 
        do_posix_clock_monotonic_gettime(&uptime);
        sinfo->connected_time = uptime.tv_sec - sta->last_connected;
@@ -404,6 +405,23 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
                sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
        sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period;
        sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int;
+
+       sinfo->sta_flags.set = 0;
+       sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
+                               BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
+                               BIT(NL80211_STA_FLAG_WME) |
+                               BIT(NL80211_STA_FLAG_MFP) |
+                               BIT(NL80211_STA_FLAG_AUTHENTICATED);
+       if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+               sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
+       if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE))
+               sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
+       if (test_sta_flag(sta, WLAN_STA_WME))
+               sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME);
+       if (test_sta_flag(sta, WLAN_STA_MFP))
+               sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP);
+       if (test_sta_flag(sta, WLAN_STA_AUTH))
+               sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
 }
 
 
@@ -557,7 +575,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
 
        sdata->vif.bss_conf.dtim_period = new->dtim_period;
 
-       rcu_assign_pointer(sdata->u.ap.beacon, new);
+       RCU_INIT_POINTER(sdata->u.ap.beacon, new);
 
        synchronize_rcu();
 
@@ -612,7 +630,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
        if (!old)
                return -ENOENT;
 
-       rcu_assign_pointer(sdata->u.ap.beacon, NULL);
+       RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
        synchronize_rcu();
        kfree(old);
 
@@ -668,7 +686,6 @@ static void sta_apply_parameters(struct ieee80211_local *local,
                                 struct sta_info *sta,
                                 struct station_parameters *params)
 {
-       unsigned long flags;
        u32 rates;
        int i, j;
        struct ieee80211_supported_band *sband;
@@ -677,49 +694,53 @@ static void sta_apply_parameters(struct ieee80211_local *local,
 
        sband = local->hw.wiphy->bands[local->oper_channel->band];
 
-       spin_lock_irqsave(&sta->flaglock, flags);
        mask = params->sta_flags_mask;
        set = params->sta_flags_set;
 
        if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
-               sta->flags &= ~WLAN_STA_AUTHORIZED;
                if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
-                       sta->flags |= WLAN_STA_AUTHORIZED;
+                       set_sta_flag(sta, WLAN_STA_AUTHORIZED);
+               else
+                       clear_sta_flag(sta, WLAN_STA_AUTHORIZED);
        }
 
        if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
-               sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
                if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
-                       sta->flags |= WLAN_STA_SHORT_PREAMBLE;
+                       set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE);
+               else
+                       clear_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE);
        }
 
        if (mask & BIT(NL80211_STA_FLAG_WME)) {
-               sta->flags &= ~WLAN_STA_WME;
-               sta->sta.wme = false;
                if (set & BIT(NL80211_STA_FLAG_WME)) {
-                       sta->flags |= WLAN_STA_WME;
+                       set_sta_flag(sta, WLAN_STA_WME);
                        sta->sta.wme = true;
+               } else {
+                       clear_sta_flag(sta, WLAN_STA_WME);
+                       sta->sta.wme = false;
                }
        }
 
        if (mask & BIT(NL80211_STA_FLAG_MFP)) {
-               sta->flags &= ~WLAN_STA_MFP;
                if (set & BIT(NL80211_STA_FLAG_MFP))
-                       sta->flags |= WLAN_STA_MFP;
+                       set_sta_flag(sta, WLAN_STA_MFP);
+               else
+                       clear_sta_flag(sta, WLAN_STA_MFP);
        }
 
        if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
-               sta->flags &= ~WLAN_STA_AUTH;
                if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
-                       sta->flags |= WLAN_STA_AUTH;
+                       set_sta_flag(sta, WLAN_STA_AUTH);
+               else
+                       clear_sta_flag(sta, WLAN_STA_AUTH);
        }
 
        if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
-               sta->flags &= ~WLAN_STA_TDLS_PEER;
                if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
-                       sta->flags |= WLAN_STA_TDLS_PEER;
+                       set_sta_flag(sta, WLAN_STA_TDLS_PEER);
+               else
+                       clear_sta_flag(sta, WLAN_STA_TDLS_PEER);
        }
-       spin_unlock_irqrestore(&sta->flaglock, flags);
 
        if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) {
                sta->sta.uapsd_queues = params->uapsd_queues;
@@ -815,12 +836,13 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
        if (!sta)
                return -ENOMEM;
 
-       sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
+       set_sta_flag(sta, WLAN_STA_AUTH);
+       set_sta_flag(sta, WLAN_STA_ASSOC);
 
        sta_apply_parameters(local, sta, params);
 
        /* Only TDLS-supporting stations can add TDLS peers */
-       if ((sta->flags & WLAN_STA_TDLS_PEER) &&
+       if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
            !((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
              sdata->vif.type == NL80211_IFTYPE_STATION))
                return -ENOTSUPP;
@@ -880,7 +902,7 @@ static int ieee80211_change_station(struct wiphy *wiphy,
        /* The TDLS bit cannot be toggled after the STA was added */
        if ((params->sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
            !!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) !=
-           !!test_sta_flags(sta, WLAN_STA_TDLS_PEER)) {
+           !!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
                rcu_read_unlock();
                return -EINVAL;
        }
@@ -900,7 +922,7 @@ static int ieee80211_change_station(struct wiphy *wiphy,
                                return -EBUSY;
                        }
 
-                       rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
+                       RCU_INIT_POINTER(vlansdata->u.vlan.sta, sta);
                }
 
                sta->sdata = vlansdata;
@@ -1882,7 +1904,7 @@ ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb)
         * so in that case userspace will have to deal with it.
         */
 
-       if (wk->offchan_tx.wait && wk->offchan_tx.frame)
+       if (wk->offchan_tx.wait && !wk->offchan_tx.status)
                cfg80211_mgmt_tx_status(wk->sdata->dev,
                                        (unsigned long) wk->offchan_tx.frame,
                                        wk->ie, wk->ie_len, false, GFP_KERNEL);
@@ -2427,6 +2449,7 @@ fail:
 static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
                               u8 *peer, enum nl80211_tdls_operation oper)
 {
+       struct sta_info *sta;
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
        if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
@@ -2441,6 +2464,15 @@ static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
 
        switch (oper) {
        case NL80211_TDLS_ENABLE_LINK:
+               rcu_read_lock();
+               sta = sta_info_get(sdata, peer);
+               if (!sta) {
+                       rcu_read_unlock();
+                       return -ENOLINK;
+               }
+
+               set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
+               rcu_read_unlock();
                break;
        case NL80211_TDLS_DISABLE_LINK:
                return sta_info_destroy_addr(sdata, peer);