status = WLAN_STATUS_REQUEST_DECLINED;
 
-       if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
+       if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "Suspend in progress. "
                       "Denying ADDBA request\n");
 
            sdata->vif.type != NL80211_IFTYPE_AP)
                return -EINVAL;
 
-       if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
+       if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "BA sessions blocked. "
                       "Denying BA session request\n");
 
                                 struct sta_info *sta,
                                 struct station_parameters *params)
 {
-       unsigned long flags;
        u32 rates;
        int i, j;
        struct ieee80211_supported_band *sband;
 
        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;
        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;
        /* 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;
        }
                        return -ENOLINK;
                }
 
-               set_sta_flags(sta, WLAN_STA_TDLS_PEER_AUTH);
+               set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
                rcu_read_unlock();
                break;
        case NL80211_TDLS_DISABLE_LINK:
 
 {
        char buf[100];
        struct sta_info *sta = file->private_data;
-       u32 staflags = get_sta_flags(sta);
+
        int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
-               staflags & WLAN_STA_AUTH ? "AUTH\n" : "",
-               staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
-               staflags & WLAN_STA_PS_STA ? "PS (sta)\n" : "",
-               staflags & WLAN_STA_PS_DRIVER ? "PS (driver)\n" : "",
-               staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
-               staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
-               staflags & WLAN_STA_WME ? "WME\n" : "",
-               staflags & WLAN_STA_WDS ? "WDS\n" : "",
-               staflags & WLAN_STA_MFP ? "MFP\n" : "");
+               test_sta_flag(sta, WLAN_STA_AUTH) ? "AUTH\n" : "",
+               test_sta_flag(sta, WLAN_STA_ASSOC) ? "ASSOC\n" : "",
+               test_sta_flag(sta, WLAN_STA_PS_STA) ? "PS (sta)\n" : "",
+               test_sta_flag(sta, WLAN_STA_PS_DRIVER) ? "PS (driver)\n" : "",
+               test_sta_flag(sta, WLAN_STA_AUTHORIZED) ? "AUTHORIZED\n" : "",
+               test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE) ? "SHORT PREAMBLE\n" : "",
+               test_sta_flag(sta, WLAN_STA_WME) ? "WME\n" : "",
+               test_sta_flag(sta, WLAN_STA_WDS) ? "WDS\n" : "",
+               test_sta_flag(sta, WLAN_STA_MFP) ? "MFP\n" : "");
        return simple_read_from_buffer(userbuf, count, ppos, buf, res);
 }
 STA_OPS(flags);
 
         * down by the code that set the flag, so this
         * need not run.
         */
-       if (test_sta_flags(sta, WLAN_STA_BLOCK_BA))
+       if (test_sta_flag(sta, WLAN_STA_BLOCK_BA))
                return;
 
        mutex_lock(&sta->ampdu_mlme.mtx);
 
                }
 
                if (sta && elems->wmm_info)
-                       set_sta_flags(sta, WLAN_STA_WME);
+                       set_sta_flag(sta, WLAN_STA_WME);
 
                rcu_read_unlock();
        }
                return NULL;
 
        sta->last_rx = jiffies;
-       set_sta_flags(sta, WLAN_STA_AUTHORIZED);
+       set_sta_flag(sta, WLAN_STA_AUTHORIZED);
 
        /* make sure mandatory rates are always added */
        sta->sta.supp_rates[band] = supp_rates |
 
                        goto err_del_interface;
                }
 
-               /* no locking required since STA is not live yet */
-               sta->flags |= WLAN_STA_AUTHORIZED;
+               /* no atomic bitop required since STA is not live yet */
+               set_sta_flag(sta, WLAN_STA_AUTHORIZED);
 
                res = sta_info_insert(sta);
                if (res) {
 
                 * some hardware cannot handle TKIP with QoS, so
                 * we indicate whether QoS could be in use.
                 */
-               if (test_sta_flags(sta, WLAN_STA_WME))
+               if (test_sta_flag(sta, WLAN_STA_WME))
                        key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
        } else {
                if (sdata->vif.type == NL80211_IFTYPE_STATION) {
                        /* same here, the AP could be using QoS */
                        ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid);
                        if (ap) {
-                               if (test_sta_flags(ap, WLAN_STA_WME))
+                               if (test_sta_flag(ap, WLAN_STA_WME))
                                        key->conf.flags |=
                                                IEEE80211_KEY_FLAG_WMM_STA;
                        }
 
        if (!sta)
                return NULL;
 
-       sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH | WLAN_STA_WME;
+       set_sta_flag(sta, WLAN_STA_AUTH);
+       set_sta_flag(sta, WLAN_STA_AUTHORIZED);
+       set_sta_flag(sta, WLAN_STA_WME);
        sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
        rate_control_rate_init(sta);
 
        __le16 llid;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
 
-       if (!test_sta_flags(sta, WLAN_STA_AUTH))
+       if (!test_sta_flag(sta, WLAN_STA_AUTH))
                return -EPERM;
 
        spin_lock_bh(&sta->lock);
                return;
        }
 
-       if (sta && !test_sta_flags(sta, WLAN_STA_AUTH)) {
+       if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) {
                mpl_dbg("Mesh plink: Action frame from non-authed peer\n");
                rcu_read_unlock();
                return;
 
 {
        struct ieee80211_if_managed *mgd = &sdata->u.mgd;
        struct sta_info *sta = NULL;
-       u32 sta_flags = 0;
+       bool authorized = false;
 
        if (!mgd->powersave)
                return false;
        rcu_read_lock();
        sta = sta_info_get(sdata, mgd->bssid);
        if (sta)
-               sta_flags = get_sta_flags(sta);
+               authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
        rcu_read_unlock();
 
-       if (!(sta_flags & WLAN_STA_AUTHORIZED))
-               return false;
-
-       return true;
+       return authorized;
 }
 
 /* need to hold RTNL or interface lock */
        mutex_lock(&local->sta_mtx);
        sta = sta_info_get(sdata, bssid);
        if (sta) {
-               set_sta_flags(sta, WLAN_STA_BLOCK_BA);
+               set_sta_flag(sta, WLAN_STA_BLOCK_BA);
                ieee80211_sta_tear_down_BA_sessions(sta, tx);
        }
        mutex_unlock(&local->sta_mtx);
                return false;
        }
 
-       set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC |
-                          WLAN_STA_ASSOC_AP);
+       set_sta_flag(sta, WLAN_STA_AUTH);
+       set_sta_flag(sta, WLAN_STA_ASSOC);
+       set_sta_flag(sta, WLAN_STA_ASSOC_AP);
        if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
-               set_sta_flags(sta, WLAN_STA_AUTHORIZED);
+               set_sta_flag(sta, WLAN_STA_AUTHORIZED);
 
        rates = 0;
        basic_rates = 0;
        rate_control_rate_init(sta);
 
        if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED)
-               set_sta_flags(sta, WLAN_STA_MFP);
+               set_sta_flag(sta, WLAN_STA_MFP);
 
        if (elems.wmm_param)
-               set_sta_flags(sta, WLAN_STA_WME);
+               set_sta_flag(sta, WLAN_STA_WME);
 
        /* sta_info_reinsert will also unlock the mutex lock */
        err = sta_info_reinsert(sta);
 
        if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
                mutex_lock(&local->sta_mtx);
                list_for_each_entry(sta, &local->sta_list, list) {
-                       set_sta_flags(sta, WLAN_STA_BLOCK_BA);
+                       set_sta_flag(sta, WLAN_STA_BLOCK_BA);
                        ieee80211_sta_tear_down_BA_sessions(sta, true);
                }
                mutex_unlock(&local->sta_mtx);
 
                      ieee80211_is_pspoll(hdr->frame_control)) &&
                     rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
                     rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
-                    (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) {
+                    (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) {
                if (rx->sta && rx->sta->dummy &&
                    ieee80211_is_data_present(hdr->frame_control)) {
                        u16 ethertype;
        struct ieee80211_local *local = sdata->local;
 
        atomic_inc(&sdata->bss->num_sta_ps);
-       set_sta_flags(sta, WLAN_STA_PS_STA);
+       set_sta_flag(sta, WLAN_STA_PS_STA);
        if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
                drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
               sdata->name, sta->sta.addr, sta->sta.aid);
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 
-       if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) {
+       if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
                printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n",
                       sdata->name, sta->sta.addr, sta->sta.aid);
        WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS));
 
        /* Don't let the same PS state be set twice */
-       in_ps = test_sta_flags(sta_inf, WLAN_STA_PS_STA);
+       in_ps = test_sta_flag(sta_inf, WLAN_STA_PS_STA);
        if ((start && in_ps) || (!start && !in_ps))
                return -EINVAL;
 
         * the uAPSD case, the station will probably be marked asleep,
         * in the PS-Poll case the station must be confused ...
         */
-       if (!test_sta_flags(rx->sta, WLAN_STA_PS_STA))
+       if (!test_sta_flag(rx->sta, WLAN_STA_PS_STA))
                return RX_CONTINUE;
 
        if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) {
-               if (!test_sta_flags(rx->sta, WLAN_STA_SP)) {
-                       if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER))
+               if (!test_sta_flag(rx->sta, WLAN_STA_SP)) {
+                       if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER))
                                ieee80211_sta_ps_deliver_poll_response(rx->sta);
                        else
-                               set_sta_flags(rx->sta, WLAN_STA_PSPOLL);
+                               set_sta_flag(rx->sta, WLAN_STA_PSPOLL);
                }
 
                /* Free PS Poll skb here instead of returning RX_DROP that would
                        return RX_CONTINUE;
 
                /* if we are in a service period, do nothing */
-               if (test_sta_flags(rx->sta, WLAN_STA_SP))
+               if (test_sta_flag(rx->sta, WLAN_STA_SP))
                        return RX_CONTINUE;
 
-               if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER))
+               if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER))
                        ieee80211_sta_ps_deliver_uapsd(rx->sta);
                else
-                       set_sta_flags(rx->sta, WLAN_STA_UAPSD);
+                       set_sta_flag(rx->sta, WLAN_STA_UAPSD);
        }
 
        return RX_CONTINUE;
            !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
            (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
             rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
-               if (test_sta_flags(sta, WLAN_STA_PS_STA)) {
+               if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
                        /*
                         * Ignore doze->wake transitions that are
                         * indicated by non-data frames, the standard
 ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
 {
        if (unlikely(!rx->sta ||
-           !test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED)))
+           !test_sta_flag(rx->sta, WLAN_STA_AUTHORIZED)))
                return -EACCES;
 
        return 0;
        if (status->flag & RX_FLAG_DECRYPTED)
                return 0;
 
-       if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) {
+       if (rx->sta && test_sta_flag(rx->sta, WLAN_STA_MFP)) {
                if (unlikely(!ieee80211_has_protected(fc) &&
                             ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
                             rx->key)) {
 
        if (sta->dead)
                return;
 
-       if (!test_sta_flags(sta, WLAN_STA_PS_STA))
+       if (!test_sta_flag(sta, WLAN_STA_PS_STA))
                ieee80211_sta_ps_deliver_wakeup(sta);
-       else if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL)) {
-               clear_sta_flags(sta, WLAN_STA_PS_DRIVER);
+       else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) {
+               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
 
                local_bh_disable();
                ieee80211_sta_ps_deliver_poll_response(sta);
                local_bh_enable();
-       } else if (test_and_clear_sta_flags(sta, WLAN_STA_UAPSD)) {
-               clear_sta_flags(sta, WLAN_STA_PS_DRIVER);
+       } else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD)) {
+               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
 
                local_bh_disable();
                ieee80211_sta_ps_deliver_uapsd(sta);
                local_bh_enable();
        } else
-               clear_sta_flags(sta, WLAN_STA_PS_DRIVER);
+               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
 }
 
 static int sta_prepare_rate_control(struct ieee80211_local *local,
                return NULL;
 
        spin_lock_init(&sta->lock);
-       spin_lock_init(&sta->flaglock);
        INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
        INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
        mutex_init(&sta->ampdu_mlme.mtx);
         * sessions -- block that to make sure the tear-down
         * will be sufficient.
         */
-       set_sta_flags(sta, WLAN_STA_BLOCK_BA);
+       set_sta_flag(sta, WLAN_STA_BLOCK_BA);
        ieee80211_sta_tear_down_BA_sessions(sta, true);
 
        spin_lock_irqsave(&local->sta_lock, flags);
 
        sta->dead = true;
 
-       if (test_and_clear_sta_flags(sta,
-                               WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) {
+       if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
+           test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
                BUG_ON(!sdata->bss);
 
+               clear_sta_flag(sta, WLAN_STA_PS_STA);
+               clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
+
                atomic_dec(&sdata->bss->num_sta_ps);
                sta_info_recalc_tim(sta);
        }
 {
        struct sta_info *sta = _sta;
 
-       clear_sta_flags(sta, WLAN_STA_PS_DRIVER | WLAN_STA_PS_STA);
+       clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
+       clear_sta_flag(sta, WLAN_STA_PS_STA);
 }
 
 /* powersave support code */
        struct sk_buff_head pending;
        int filtered = 0, buffered = 0, ac;
 
-       clear_sta_flags(sta, WLAN_STA_SP);
+       clear_sta_flag(sta, WLAN_STA_SP);
 
        BUILD_BUG_ON(BITS_TO_LONGS(STA_TID_NUM) > 1);
        sta->driver_buffered_tids = 0;
        struct sk_buff *skb;
        int size = sizeof(*nullfunc);
        __le16 fc;
-       bool qos = test_sta_flags(sta, WLAN_STA_WME);
+       bool qos = test_sta_flag(sta, WLAN_STA_WME);
        struct ieee80211_tx_info *info;
 
        if (qos) {
        struct sk_buff_head frames;
 
        /* Service or PS-Poll period starts */
-       set_sta_flags(sta, WLAN_STA_SP);
+       set_sta_flag(sta, WLAN_STA_SP);
 
        __skb_queue_head_init(&frames);
 
        trace_api_sta_block_awake(sta->local, pubsta, block);
 
        if (block)
-               set_sta_flags(sta, WLAN_STA_PS_DRIVER);
-       else if (test_sta_flags(sta, WLAN_STA_PS_DRIVER))
+               set_sta_flag(sta, WLAN_STA_PS_DRIVER);
+       else if (test_sta_flag(sta, WLAN_STA_PS_DRIVER))
                ieee80211_queue_work(hw, &sta->drv_unblock_wk);
 }
 EXPORT_SYMBOL(ieee80211_sta_block_awake);
 
 /**
  * enum ieee80211_sta_info_flags - Stations flags
  *
- * These flags are used with &struct sta_info's @flags member.
+ * These flags are used with &struct sta_info's @flags member, but
+ * only indirectly with set_sta_flag() and friends.
  *
  * @WLAN_STA_AUTH: Station is authenticated.
  * @WLAN_STA_ASSOC: Station is associated.
  *     reply to other uAPSD trigger frames or PS-Poll.
  */
 enum ieee80211_sta_info_flags {
-       WLAN_STA_AUTH           = 1<<0,
-       WLAN_STA_ASSOC          = 1<<1,
-       WLAN_STA_PS_STA         = 1<<2,
-       WLAN_STA_AUTHORIZED     = 1<<3,
-       WLAN_STA_SHORT_PREAMBLE = 1<<4,
-       WLAN_STA_ASSOC_AP       = 1<<5,
-       WLAN_STA_WME            = 1<<6,
-       WLAN_STA_WDS            = 1<<7,
-       WLAN_STA_CLEAR_PS_FILT  = 1<<9,
-       WLAN_STA_MFP            = 1<<10,
-       WLAN_STA_BLOCK_BA       = 1<<11,
-       WLAN_STA_PS_DRIVER      = 1<<12,
-       WLAN_STA_PSPOLL         = 1<<13,
-       WLAN_STA_TDLS_PEER      = 1<<15,
-       WLAN_STA_TDLS_PEER_AUTH = 1<<16,
-       WLAN_STA_UAPSD          = 1<<17,
-       WLAN_STA_SP             = 1<<18,
+       WLAN_STA_AUTH,
+       WLAN_STA_ASSOC,
+       WLAN_STA_PS_STA,
+       WLAN_STA_AUTHORIZED,
+       WLAN_STA_SHORT_PREAMBLE,
+       WLAN_STA_ASSOC_AP,
+       WLAN_STA_WME,
+       WLAN_STA_WDS,
+       WLAN_STA_CLEAR_PS_FILT,
+       WLAN_STA_MFP,
+       WLAN_STA_BLOCK_BA,
+       WLAN_STA_PS_DRIVER,
+       WLAN_STA_PSPOLL,
+       WLAN_STA_TDLS_PEER,
+       WLAN_STA_TDLS_PEER_AUTH,
+       WLAN_STA_UAPSD,
+       WLAN_STA_SP,
 };
 
 #define STA_TID_NUM 16
  * @last_rx_rate_flag: rx status flag of the last data packet
  * @lock: used for locking all fields that require locking, see comments
  *     in the header file.
- * @flaglock: spinlock for flags accesses
  * @drv_unblock_wk: used for driver PS unblocking
  * @listen_interval: listen interval of this station, when we're acting as AP
- * @flags: STA flags, see &enum ieee80211_sta_info_flags
+ * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
  * @ps_tx_buf: buffers (per AC) of frames to transmit to this station
  *     when it leaves power saving state or polls
  * @tx_filtered: buffers (per AC) of frames we already tried to
        struct rate_control_ref *rate_ctrl;
        void *rate_ctrl_priv;
        spinlock_t lock;
-       spinlock_t flaglock;
 
        struct work_struct drv_unblock_wk;
 
 
        bool uploaded;
 
-       /*
-        * frequently updated, locked with own spinlock (flaglock),
-        * use the accessors defined below
-        */
-       u32 flags;
+       /* use the accessors defined below */
+       unsigned long _flags;
 
        /*
         * STA powersave frame queues, no more than the internal
        return NL80211_PLINK_LISTEN;
 }
 
-static inline void set_sta_flags(struct sta_info *sta, const u32 flags)
+static inline void set_sta_flag(struct sta_info *sta,
+                               enum ieee80211_sta_info_flags flag)
 {
-       unsigned long irqfl;
-
-       spin_lock_irqsave(&sta->flaglock, irqfl);
-       sta->flags |= flags;
-       spin_unlock_irqrestore(&sta->flaglock, irqfl);
+       set_bit(flag, &sta->_flags);
 }
 
-static inline void clear_sta_flags(struct sta_info *sta, const u32 flags)
+static inline void clear_sta_flag(struct sta_info *sta,
+                                 enum ieee80211_sta_info_flags flag)
 {
-       unsigned long irqfl;
-
-       spin_lock_irqsave(&sta->flaglock, irqfl);
-       sta->flags &= ~flags;
-       spin_unlock_irqrestore(&sta->flaglock, irqfl);
+       clear_bit(flag, &sta->_flags);
 }
 
-static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags)
+static inline int test_sta_flag(struct sta_info *sta,
+                               enum ieee80211_sta_info_flags flag)
 {
-       u32 ret;
-       unsigned long irqfl;
-
-       spin_lock_irqsave(&sta->flaglock, irqfl);
-       ret = sta->flags & flags;
-       spin_unlock_irqrestore(&sta->flaglock, irqfl);
-
-       return ret;
+       return test_bit(flag, &sta->_flags);
 }
 
-static inline u32 test_and_clear_sta_flags(struct sta_info *sta,
-                                          const u32 flags)
+static inline int test_and_clear_sta_flag(struct sta_info *sta,
+                                         enum ieee80211_sta_info_flags flag)
 {
-       u32 ret;
-       unsigned long irqfl;
-
-       spin_lock_irqsave(&sta->flaglock, irqfl);
-       ret = sta->flags & flags;
-       sta->flags &= ~flags;
-       spin_unlock_irqrestore(&sta->flaglock, irqfl);
-
-       return ret;
-}
-
-static inline u32 get_sta_flags(struct sta_info *sta)
-{
-       u32 ret;
-       unsigned long irqfl;
-
-       spin_lock_irqsave(&sta->flaglock, irqfl);
-       ret = sta->flags;
-       spin_unlock_irqrestore(&sta->flaglock, irqfl);
-
-       return ret;
+       return test_and_clear_bit(flag, &sta->_flags);
 }
 
 void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
 
         * packet. If the STA went to power save mode, this will happen
         * when it wakes up for the next time.
         */
-       set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT);
+       set_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT);
 
        /*
         * This code races in the following way:
         *      changes before calling TX status events if ordering can be
         *      unknown.
         */
-       if (test_sta_flags(sta, WLAN_STA_PS_STA) &&
+       if (test_sta_flag(sta, WLAN_STA_PS_STA) &&
            skb_queue_len(&sta->tx_filtered[ac]) < STA_MAX_TX_BUFFER) {
                skb_queue_tail(&sta->tx_filtered[ac], skb);
                sta_info_recalc_tim(sta);
                return;
        }
 
-       if (!test_sta_flags(sta, WLAN_STA_PS_STA) &&
+       if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
            !(info->flags & IEEE80211_TX_INTFL_RETRIED)) {
                /* Software retry the packet once */
                info->flags |= IEEE80211_TX_INTFL_RETRIED;
                wiphy_debug(local->hw.wiphy,
                            "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n",
                            skb_queue_len(&sta->tx_filtered[ac]),
-                           !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies);
+                           !!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies);
 #endif
        dev_kfree_skb(skb);
 }
                        continue;
 
                if (info->flags & IEEE80211_TX_STATUS_EOSP)
-                       clear_sta_flags(sta, WLAN_STA_SP);
+                       clear_sta_flag(sta, WLAN_STA_SP);
 
                acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
-               if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) {
+               if (!acked && test_sta_flag(sta, WLAN_STA_PS_STA)) {
                        /*
                         * The STA is in power save mode, so assume
                         * that this TX packet failed because of that.
 
 
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
-       u32 sta_flags;
+       bool assoc = false;
 
        if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
                return TX_CONTINUE;
        if (tx->flags & IEEE80211_TX_PS_BUFFERED)
                return TX_CONTINUE;
 
-       sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0;
+       if (tx->sta)
+               assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
 
        if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
-               if (unlikely(!(sta_flags & WLAN_STA_ASSOC) &&
+               if (unlikely(!assoc &&
                             tx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
                             ieee80211_is_data(hdr->frame_control))) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
        if (!ieee80211_is_mgmt(fc))
                return 0;
 
-       if (sta == NULL || !test_sta_flags(sta, WLAN_STA_MFP))
+       if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP))
                return 0;
 
        if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *)
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
        struct ieee80211_local *local = tx->local;
-       u32 staflags;
 
        if (unlikely(!sta ||
                     ieee80211_is_probe_resp(hdr->frame_control) ||
                     ieee80211_is_reassoc_resp(hdr->frame_control)))
                return TX_CONTINUE;
 
-       staflags = get_sta_flags(sta);
-
-       if (unlikely((staflags & (WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) &&
+       if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) ||
+                     test_sta_flag(sta, WLAN_STA_PS_DRIVER)) &&
                     !(info->flags & IEEE80211_TX_CTL_POLL_RESPONSE))) {
                int ac = skb_get_queue_mapping(tx->skb);
 
                return TX_QUEUED;
        }
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-       else if (unlikely(staflags & WLAN_STA_PS_STA)) {
+       else if (unlikely(test_sta_flag(sta, WLAN_STA_PS_STA))) {
                printk(KERN_DEBUG
                       "%s: STA %pM in PS mode, but polling/in SP -> send frame\n",
                       tx->sdata->name, sta->sta.addr);
                 !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
                 (!ieee80211_is_robust_mgmt_frame(hdr) ||
                  (ieee80211_is_action(hdr->frame_control) &&
-                  tx->sta && test_sta_flags(tx->sta, WLAN_STA_MFP)))) {
+                  tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))) {
                I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
                return TX_DROP;
        } else
        u32 len;
        bool inval = false, rts = false, short_preamble = false;
        struct ieee80211_tx_rate_control txrc;
-       u32 sta_flags;
+       bool assoc = false;
 
        memset(&txrc, 0, sizeof(txrc));
 
         */
        if (tx->sdata->vif.bss_conf.use_short_preamble &&
            (ieee80211_is_data(hdr->frame_control) ||
-            (tx->sta && test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))))
+            (tx->sta && test_sta_flag(tx->sta, WLAN_STA_SHORT_PREAMBLE))))
                txrc.short_preamble = short_preamble = true;
 
-       sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0;
+       if (tx->sta)
+               assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
 
        /*
         * Lets not bother rate control if we're associated and cannot
         * talk to the sta. This should not happen.
         */
-       if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) &&
-                (sta_flags & WLAN_STA_ASSOC) &&
+       if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) && assoc &&
                 !rate_usable_index_exists(sband, &tx->sta->sta),
                 "%s: Dropped data frame as no usable bitrate found while "
                 "scanning and associated. Target station: "
 
        if (!tx->sta)
                info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
-       else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT))
+       else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT))
                info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
 
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
        int encaps_len, skip_header_bytes;
        int nh_pos, h_pos;
        struct sta_info *sta = NULL;
-       u32 sta_flags = 0;
+       bool wme_sta = false, authorized = false, tdls_auth = false;
        struct sk_buff *tmp_skb;
        bool tdls_direct = false;
 
                        memcpy(hdr.addr3, skb->data, ETH_ALEN);
                        memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
                        hdrlen = 30;
-                       sta_flags = get_sta_flags(sta);
+                       authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
+                       wme_sta = test_sta_flag(sta, WLAN_STA_WME);
                }
                rcu_read_unlock();
                if (sta)
 #endif
        case NL80211_IFTYPE_STATION:
                if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) {
+                       bool tdls_peer = false;
+
                        rcu_read_lock();
                        sta = sta_info_get(sdata, skb->data);
-                       if (sta)
-                               sta_flags = get_sta_flags(sta);
+                       if (sta) {
+                               authorized = test_sta_flag(sta,
+                                                       WLAN_STA_AUTHORIZED);
+                               wme_sta = test_sta_flag(sta, WLAN_STA_WME);
+                               tdls_peer = test_sta_flag(sta,
+                                                        WLAN_STA_TDLS_PEER);
+                               tdls_auth = test_sta_flag(sta,
+                                               WLAN_STA_TDLS_PEER_AUTH);
+                       }
                        rcu_read_unlock();
 
                        /*
                         * directly. Otherwise, allow TDLS setup frames
                         * to be transmitted indirectly.
                         */
-                       tdls_direct =
-                               (sta_flags & WLAN_STA_TDLS_PEER) &&
-                               ((sta_flags & WLAN_STA_TDLS_PEER_AUTH) ||
+                       tdls_direct = tdls_peer && (tdls_auth ||
                                 !(ethertype == ETH_P_TDLS && skb->len > 14 &&
                                   skb->data[14] == WLAN_TDLS_SNAP_RFTYPE));
                }
 
                if (tdls_direct) {
                        /* link during setup - throw out frames to peer */
-                       if (!(sta_flags & WLAN_STA_TDLS_PEER_AUTH)) {
+                       if (!tdls_auth) {
                                ret = NETDEV_TX_OK;
                                goto fail;
                        }
        if (!is_multicast_ether_addr(hdr.addr1)) {
                rcu_read_lock();
                sta = sta_info_get(sdata, hdr.addr1);
-               if (sta)
-                       sta_flags = get_sta_flags(sta);
+               if (sta) {
+                       authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
+                       wme_sta = test_sta_flag(sta, WLAN_STA_WME);
+               }
                rcu_read_unlock();
        }
 
        /* For mesh, the use of the QoS header is mandatory */
        if (ieee80211_vif_is_mesh(&sdata->vif))
-               sta_flags |= WLAN_STA_WME;
+               wme_sta = true;
 
        /* receiver and we are QoS enabled, use a QoS type frame */
-       if ((sta_flags & WLAN_STA_WME) && local->hw.queues >= 4) {
+       if (wme_sta && local->hw.queues >= 4) {
                fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
                hdrlen += 2;
        }
         * EAPOL frames from the local station.
         */
        if (!ieee80211_vif_is_mesh(&sdata->vif) &&
-               unlikely(!is_multicast_ether_addr(hdr.addr1) &&
-                     !(sta_flags & WLAN_STA_AUTHORIZED) &&
+               unlikely(!is_multicast_ether_addr(hdr.addr1) && !authorized &&
                      !(cpu_to_be16(ethertype) == sdata->control_port_protocol &&
                       compare_ether_addr(sdata->vif.addr,
                                          skb->data + ETH_ALEN) == 0))) {
 
 
                list_for_each_entry(sta, &local->sta_list, list) {
                        ieee80211_sta_tear_down_BA_sessions(sta, true);
-                       clear_sta_flags(sta, WLAN_STA_BLOCK_BA);
+                       clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
                }
 
                mutex_unlock(&local->sta_mtx);
 
        case NL80211_IFTYPE_AP_VLAN:
                sta = rcu_dereference(sdata->u.vlan.sta);
                if (sta) {
-                       qos = get_sta_flags(sta) & WLAN_STA_WME;
+                       qos = test_sta_flag(sta, WLAN_STA_WME);
                        break;
                }
        case NL80211_IFTYPE_AP:
        if (!sta && ra && !is_multicast_ether_addr(ra)) {
                sta = sta_info_get(sdata, ra);
                if (sta)
-                       qos = get_sta_flags(sta) & WLAN_STA_WME;
+                       qos = test_sta_flag(sta, WLAN_STA_WME);
        }
        rcu_read_unlock();