]> Pileus Git - ~andy/linux/blobdiff - net/mac80211/mlme.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[~andy/linux] / net / mac80211 / mlme.c
index 741448b308257c3a6f01c3d09ca36d7ddaa31ca3..118540b16729be256abbc2b4c2bf756ac44304b4 100644 (file)
@@ -90,41 +90,6 @@ MODULE_PARM_DESC(probe_wait_ms,
  */
 #define IEEE80211_SIGNAL_AVE_MIN_COUNT 4
 
-/*
- * All cfg80211 functions have to be called outside a locked
- * section so that they can acquire a lock themselves... This
- * is much simpler than queuing up things in cfg80211, but we
- * do need some indirection for that here.
- */
-enum rx_mgmt_action {
-       /* no action required */
-       RX_MGMT_NONE,
-
-       /* caller must call cfg80211_send_deauth() */
-       RX_MGMT_CFG80211_DEAUTH,
-
-       /* caller must call cfg80211_send_disassoc() */
-       RX_MGMT_CFG80211_DISASSOC,
-
-       /* caller must call cfg80211_send_rx_auth() */
-       RX_MGMT_CFG80211_RX_AUTH,
-
-       /* caller must call cfg80211_send_rx_assoc() */
-       RX_MGMT_CFG80211_RX_ASSOC,
-
-       /* caller must call cfg80211_send_assoc_timeout() */
-       RX_MGMT_CFG80211_ASSOC_TIMEOUT,
-
-       /* used when a processed beacon causes a deauth */
-       RX_MGMT_CFG80211_TX_DEAUTH,
-};
-
-/* utils */
-static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
-{
-       lockdep_assert_held(&ifmgd->mtx);
-}
-
 /*
  * We can have multiple work items (and connection probing)
  * scheduling this timer, but we need to take care to only
@@ -135,13 +100,14 @@ static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
  * has happened -- the work that runs from this timer will
  * do that.
  */
-static void run_again(struct ieee80211_if_managed *ifmgd, unsigned long timeout)
+static void run_again(struct ieee80211_sub_if_data *sdata,
+                     unsigned long timeout)
 {
-       ASSERT_MGD_MTX(ifmgd);
+       sdata_assert_lock(sdata);
 
-       if (!timer_pending(&ifmgd->timer) ||
-           time_before(timeout, ifmgd->timer.expires))
-               mod_timer(&ifmgd->timer, timeout);
+       if (!timer_pending(&sdata->u.mgd.timer) ||
+           time_before(timeout, sdata->u.mgd.timer.expires))
+               mod_timer(&sdata->u.mgd.timer, timeout);
 }
 
 void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
@@ -652,7 +618,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
        struct ieee80211_channel *chan;
        u32 rates = 0;
 
-       lockdep_assert_held(&ifmgd->mtx);
+       sdata_assert_lock(sdata);
 
        rcu_read_lock();
        chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
@@ -962,7 +928,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
        if (!ieee80211_sdata_running(sdata))
                return;
 
-       mutex_lock(&ifmgd->mtx);
+       sdata_lock(sdata);
        if (!ifmgd->associated)
                goto out;
 
@@ -985,7 +951,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
                                        IEEE80211_QUEUE_STOP_REASON_CSA);
  out:
        ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
-       mutex_unlock(&ifmgd->mtx);
+       sdata_unlock(sdata);
 }
 
 void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
@@ -1036,7 +1002,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
        const struct ieee80211_ht_operation *ht_oper;
        int secondary_channel_offset = -1;
 
-       ASSERT_MGD_MTX(ifmgd);
+       sdata_assert_lock(sdata);
 
        if (!cbss)
                return;
@@ -1390,6 +1356,9 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
                          IEEE80211_STA_CONNECTION_POLL))
                return false;
 
+       if (!sdata->vif.bss_conf.dtim_period)
+               return false;
+
        rcu_read_lock();
        sta = sta_info_get(sdata, mgd->bssid);
        if (sta)
@@ -1842,7 +1811,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_local *local = sdata->local;
        u32 changed = 0;
 
-       ASSERT_MGD_MTX(ifmgd);
+       sdata_assert_lock(sdata);
 
        if (WARN_ON_ONCE(tx && !frame_buf))
                return;
@@ -2051,7 +2020,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
        }
 
        ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
-       run_again(ifmgd, ifmgd->probe_timeout);
+       run_again(sdata, ifmgd->probe_timeout);
        if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
                ieee80211_flush_queues(sdata->local, sdata);
 }
@@ -2065,7 +2034,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
        if (!ieee80211_sdata_running(sdata))
                return;
 
-       mutex_lock(&ifmgd->mtx);
+       sdata_lock(sdata);
 
        if (!ifmgd->associated)
                goto out;
@@ -2119,7 +2088,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
        ifmgd->probe_send_count = 0;
        ieee80211_mgd_probe_ap_send(sdata);
  out:
-       mutex_unlock(&ifmgd->mtx);
+       sdata_unlock(sdata);
 }
 
 struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
@@ -2135,7 +2104,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
        if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
                return NULL;
 
-       ASSERT_MGD_MTX(ifmgd);
+       sdata_assert_lock(sdata);
 
        if (ifmgd->associated)
                cbss = ifmgd->associated;
@@ -2168,9 +2137,9 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
 
-       mutex_lock(&ifmgd->mtx);
+       sdata_lock(sdata);
        if (!ifmgd->associated) {
-               mutex_unlock(&ifmgd->mtx);
+               sdata_unlock(sdata);
                return;
        }
 
@@ -2181,13 +2150,9 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
        ieee80211_wake_queues_by_reason(&sdata->local->hw,
                                        IEEE80211_MAX_QUEUE_MAP,
                                        IEEE80211_QUEUE_STOP_REASON_CSA);
-       mutex_unlock(&ifmgd->mtx);
 
-       /*
-        * must be outside lock due to cfg80211,
-        * but that's not a problem.
-        */
        cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
+       sdata_unlock(sdata);
 }
 
 static void ieee80211_beacon_connection_loss_work(struct work_struct *work)
@@ -2254,7 +2219,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data;
 
-       lockdep_assert_held(&sdata->u.mgd.mtx);
+       sdata_assert_lock(sdata);
 
        if (!assoc) {
                sta_info_destroy_addr(sdata, auth_data->bss->bssid);
@@ -2295,27 +2260,26 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
                            auth_data->key_idx, tx_flags);
 }
 
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
-                      struct ieee80211_mgmt *mgmt, size_t len)
+static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
+                                  struct ieee80211_mgmt *mgmt, size_t len)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        u8 bssid[ETH_ALEN];
        u16 auth_alg, auth_transaction, status_code;
        struct sta_info *sta;
 
-       lockdep_assert_held(&ifmgd->mtx);
+       sdata_assert_lock(sdata);
 
        if (len < 24 + 6)
-               return RX_MGMT_NONE;
+               return;
 
        if (!ifmgd->auth_data || ifmgd->auth_data->done)
-               return RX_MGMT_NONE;
+               return;
 
        memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN);
 
        if (!ether_addr_equal(bssid, mgmt->bssid))
-               return RX_MGMT_NONE;
+               return;
 
        auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
        auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
@@ -2327,14 +2291,15 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
                           mgmt->sa, auth_alg, ifmgd->auth_data->algorithm,
                           auth_transaction,
                           ifmgd->auth_data->expected_transaction);
-               return RX_MGMT_NONE;
+               return;
        }
 
        if (status_code != WLAN_STATUS_SUCCESS) {
                sdata_info(sdata, "%pM denied authentication (status %d)\n",
                           mgmt->sa, status_code);
                ieee80211_destroy_auth_data(sdata, false);
-               return RX_MGMT_CFG80211_RX_AUTH;
+               cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);
+               return;
        }
 
        switch (ifmgd->auth_data->algorithm) {
@@ -2347,20 +2312,20 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
                if (ifmgd->auth_data->expected_transaction != 4) {
                        ieee80211_auth_challenge(sdata, mgmt, len);
                        /* need another frame */
-                       return RX_MGMT_NONE;
+                       return;
                }
                break;
        default:
                WARN_ONCE(1, "invalid auth alg %d",
                          ifmgd->auth_data->algorithm);
-               return RX_MGMT_NONE;
+               return;
        }
 
        sdata_info(sdata, "authenticated\n");
        ifmgd->auth_data->done = true;
        ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
        ifmgd->auth_data->timeout_started = true;
-       run_again(ifmgd, ifmgd->auth_data->timeout);
+       run_again(sdata, ifmgd->auth_data->timeout);
 
        if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
            ifmgd->auth_data->expected_transaction != 2) {
@@ -2368,7 +2333,8 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
                 * Report auth frame to user space for processing since another
                 * round of Authentication frames is still needed.
                 */
-               return RX_MGMT_CFG80211_RX_AUTH;
+               cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);
+               return;
        }
 
        /* move station state to auth */
@@ -2384,30 +2350,29 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
        }
        mutex_unlock(&sdata->local->sta_mtx);
 
-       return RX_MGMT_CFG80211_RX_AUTH;
+       cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);
+       return;
  out_err:
        mutex_unlock(&sdata->local->sta_mtx);
        /* ignore frame -- wait for timeout */
-       return RX_MGMT_NONE;
 }
 
 
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
-                        struct ieee80211_mgmt *mgmt, size_t len)
+static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
+                                    struct ieee80211_mgmt *mgmt, size_t len)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        const u8 *bssid = NULL;
        u16 reason_code;
 
-       lockdep_assert_held(&ifmgd->mtx);
+       sdata_assert_lock(sdata);
 
        if (len < 24 + 2)
-               return RX_MGMT_NONE;
+               return;
 
        if (!ifmgd->associated ||
            !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
-               return RX_MGMT_NONE;
+               return;
 
        bssid = ifmgd->associated->bssid;
 
@@ -2418,25 +2383,24 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
 
        ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
 
-       return RX_MGMT_CFG80211_DEAUTH;
+       cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, len);
 }
 
 
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
-                          struct ieee80211_mgmt *mgmt, size_t len)
+static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
+                                      struct ieee80211_mgmt *mgmt, size_t len)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        u16 reason_code;
 
-       lockdep_assert_held(&ifmgd->mtx);
+       sdata_assert_lock(sdata);
 
        if (len < 24 + 2)
-               return RX_MGMT_NONE;
+               return;
 
        if (!ifmgd->associated ||
            !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
-               return RX_MGMT_NONE;
+               return;
 
        reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
 
@@ -2445,7 +2409,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
 
        ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
 
-       return RX_MGMT_CFG80211_DISASSOC;
+       cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, len);
 }
 
 static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
@@ -2495,7 +2459,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
 
-       lockdep_assert_held(&sdata->u.mgd.mtx);
+       sdata_assert_lock(sdata);
 
        if (!assoc) {
                sta_info_destroy_addr(sdata, assoc_data->bss->bssid);
@@ -2749,10 +2713,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
        return ret;
 }
 
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
-                            struct ieee80211_mgmt *mgmt, size_t len,
-                            struct cfg80211_bss **bss)
+static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+                                        struct ieee80211_mgmt *mgmt,
+                                        size_t len)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
@@ -2760,13 +2723,14 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        struct ieee802_11_elems elems;
        u8 *pos;
        bool reassoc;
+       struct cfg80211_bss *bss;
 
-       lockdep_assert_held(&ifmgd->mtx);
+       sdata_assert_lock(sdata);
 
        if (!assoc_data)
-               return RX_MGMT_NONE;
+               return;
        if (!ether_addr_equal(assoc_data->bss->bssid, mgmt->bssid))
-               return RX_MGMT_NONE;
+               return;
 
        /*
         * AssocResp and ReassocResp have identical structure, so process both
@@ -2774,7 +2738,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
         */
 
        if (len < 24 + 6)
-               return RX_MGMT_NONE;
+               return;
 
        reassoc = ieee80211_is_reassoc_req(mgmt->frame_control);
        capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
@@ -2801,22 +2765,23 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
                assoc_data->timeout = jiffies + msecs_to_jiffies(ms);
                assoc_data->timeout_started = true;
                if (ms > IEEE80211_ASSOC_TIMEOUT)
-                       run_again(ifmgd, assoc_data->timeout);
-               return RX_MGMT_NONE;
+                       run_again(sdata, assoc_data->timeout);
+               return;
        }
 
-       *bss = assoc_data->bss;
+       bss = assoc_data->bss;
 
        if (status_code != WLAN_STATUS_SUCCESS) {
                sdata_info(sdata, "%pM denied association (code=%d)\n",
                           mgmt->sa, status_code);
                ieee80211_destroy_assoc_data(sdata, false);
        } else {
-               if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) {
+               if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) {
                        /* oops -- internal error -- send timeout for now */
                        ieee80211_destroy_assoc_data(sdata, false);
-                       cfg80211_put_bss(sdata->local->hw.wiphy, *bss);
-                       return RX_MGMT_CFG80211_ASSOC_TIMEOUT;
+                       cfg80211_put_bss(sdata->local->hw.wiphy, bss);
+                       cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid);
+                       return;
                }
                sdata_info(sdata, "associated\n");
 
@@ -2828,7 +2793,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
                ieee80211_destroy_assoc_data(sdata, true);
        }
 
-       return RX_MGMT_CFG80211_RX_ASSOC;
+       cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, len);
 }
 
 static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
@@ -2842,7 +2807,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_channel *channel;
        bool need_ps = false;
 
-       lockdep_assert_held(&sdata->u.mgd.mtx);
+       sdata_assert_lock(sdata);
 
        if ((sdata->u.mgd.associated &&
             ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) ||
@@ -2901,7 +2866,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
 
        ifmgd = &sdata->u.mgd;
 
-       ASSERT_MGD_MTX(ifmgd);
+       sdata_assert_lock(sdata);
 
        if (!ether_addr_equal(mgmt->da, sdata->vif.addr))
                return; /* ignore ProbeResp to foreign address */
@@ -2926,7 +2891,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
                ifmgd->auth_data->tries = 0;
                ifmgd->auth_data->timeout = jiffies;
                ifmgd->auth_data->timeout_started = true;
-               run_again(ifmgd, ifmgd->auth_data->timeout);
+               run_again(sdata, ifmgd->auth_data->timeout);
        }
 }
 
@@ -2951,10 +2916,9 @@ static const u64 care_about_ies =
        (1ULL << WLAN_EID_HT_CAPABILITY) |
        (1ULL << WLAN_EID_HT_OPERATION);
 
-static enum rx_mgmt_action
-ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
-                        struct ieee80211_mgmt *mgmt, size_t len,
-                        u8 *deauth_buf, struct ieee80211_rx_status *rx_status)
+static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
+                                    struct ieee80211_mgmt *mgmt, size_t len,
+                                    struct ieee80211_rx_status *rx_status)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
@@ -2969,24 +2933,25 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
        u8 erp_value = 0;
        u32 ncrc;
        u8 *bssid;
+       u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
 
-       lockdep_assert_held(&ifmgd->mtx);
+       sdata_assert_lock(sdata);
 
        /* Process beacon from the current BSS */
        baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
        if (baselen > len)
-               return RX_MGMT_NONE;
+               return;
 
        rcu_read_lock();
        chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
        if (!chanctx_conf) {
                rcu_read_unlock();
-               return RX_MGMT_NONE;
+               return;
        }
 
        if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
                rcu_read_unlock();
-               return RX_MGMT_NONE;
+               return;
        }
        chan = chanctx_conf->def.chan;
        rcu_read_unlock();
@@ -3013,13 +2978,13 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                /* continue assoc process */
                ifmgd->assoc_data->timeout = jiffies;
                ifmgd->assoc_data->timeout_started = true;
-               run_again(ifmgd, ifmgd->assoc_data->timeout);
-               return RX_MGMT_NONE;
+               run_again(sdata, ifmgd->assoc_data->timeout);
+               return;
        }
 
        if (!ifmgd->associated ||
            !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
-               return RX_MGMT_NONE;
+               return;
        bssid = ifmgd->associated->bssid;
 
        /* Track average RSSI from the Beacon frames of the current AP */
@@ -3165,7 +3130,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
        }
 
        if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
-               return RX_MGMT_NONE;
+               return;
        ifmgd->beacon_crc = ncrc;
        ifmgd->beacon_crc_valid = true;
 
@@ -3199,6 +3164,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                }
 
                changed |= BSS_CHANGED_DTIM_PERIOD;
+               ieee80211_recalc_ps_vif(sdata);
        }
 
        if (elems.erp_info) {
@@ -3220,7 +3186,9 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
                                       WLAN_REASON_DEAUTH_LEAVING,
                                       true, deauth_buf);
-               return RX_MGMT_CFG80211_TX_DEAUTH;
+               cfg80211_send_deauth(sdata->dev, deauth_buf,
+                                    sizeof(deauth_buf));
+               return;
        }
 
        if (sta && elems.opmode_notif)
@@ -3237,19 +3205,13 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                                                       elems.pwr_constr_elem);
 
        ieee80211_bss_info_change_notify(sdata, changed);
-
-       return RX_MGMT_NONE;
 }
 
 void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
                                  struct sk_buff *skb)
 {
-       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_rx_status *rx_status;
        struct ieee80211_mgmt *mgmt;
-       struct cfg80211_bss *bss = NULL;
-       enum rx_mgmt_action rma = RX_MGMT_NONE;
-       u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
        u16 fc;
        struct ieee802_11_elems elems;
        int ies_len;
@@ -3258,28 +3220,27 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
        mgmt = (struct ieee80211_mgmt *) skb->data;
        fc = le16_to_cpu(mgmt->frame_control);
 
-       mutex_lock(&ifmgd->mtx);
+       sdata_lock(sdata);
 
        switch (fc & IEEE80211_FCTL_STYPE) {
        case IEEE80211_STYPE_BEACON:
-               rma = ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
-                                              deauth_buf, rx_status);
+               ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status);
                break;
        case IEEE80211_STYPE_PROBE_RESP:
                ieee80211_rx_mgmt_probe_resp(sdata, skb);
                break;
        case IEEE80211_STYPE_AUTH:
-               rma = ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
+               ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
                break;
        case IEEE80211_STYPE_DEAUTH:
-               rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
+               ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
                break;
        case IEEE80211_STYPE_DISASSOC:
-               rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
+               ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
                break;
        case IEEE80211_STYPE_ASSOC_RESP:
        case IEEE80211_STYPE_REASSOC_RESP:
-               rma = ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, &bss);
+               ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len);
                break;
        case IEEE80211_STYPE_ACTION:
                if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
@@ -3325,34 +3286,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
                }
                break;
        }
-       mutex_unlock(&ifmgd->mtx);
-
-       switch (rma) {
-       case RX_MGMT_NONE:
-               /* no action */
-               break;
-       case RX_MGMT_CFG80211_DEAUTH:
-               cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
-               break;
-       case RX_MGMT_CFG80211_DISASSOC:
-               cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
-               break;
-       case RX_MGMT_CFG80211_RX_AUTH:
-               cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, skb->len);
-               break;
-       case RX_MGMT_CFG80211_RX_ASSOC:
-               cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, skb->len);
-               break;
-       case RX_MGMT_CFG80211_ASSOC_TIMEOUT:
-               cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid);
-               break;
-       case RX_MGMT_CFG80211_TX_DEAUTH:
-               cfg80211_send_deauth(sdata->dev, deauth_buf,
-                                    sizeof(deauth_buf));
-               break;
-       default:
-               WARN(1, "unexpected: %d", rma);
-       }
+       sdata_unlock(sdata);
 }
 
 static void ieee80211_sta_timer(unsigned long data)
@@ -3366,20 +3300,12 @@ static void ieee80211_sta_timer(unsigned long data)
 static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
                                          u8 *bssid, u8 reason, bool tx)
 {
-       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
 
        ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
                               tx, frame_buf);
-       mutex_unlock(&ifmgd->mtx);
 
-       /*
-        * must be outside lock due to cfg80211,
-        * but that's not a problem.
-        */
        cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
-
-       mutex_lock(&ifmgd->mtx);
 }
 
 static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
@@ -3389,7 +3315,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
        struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data;
        u32 tx_flags = 0;
 
-       lockdep_assert_held(&ifmgd->mtx);
+       sdata_assert_lock(sdata);
 
        if (WARN_ON_ONCE(!auth_data))
                return -EINVAL;
@@ -3462,7 +3388,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
        if (tx_flags == 0) {
                auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
                ifmgd->auth_data->timeout_started = true;
-               run_again(ifmgd, auth_data->timeout);
+               run_again(sdata, auth_data->timeout);
        } else {
                auth_data->timeout_started = false;
        }
@@ -3475,7 +3401,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
        struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
        struct ieee80211_local *local = sdata->local;
 
-       lockdep_assert_held(&sdata->u.mgd.mtx);
+       sdata_assert_lock(sdata);
 
        assoc_data->tries++;
        if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) {
@@ -3499,7 +3425,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
        if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
                assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
                assoc_data->timeout_started = true;
-               run_again(&sdata->u.mgd, assoc_data->timeout);
+               run_again(sdata, assoc_data->timeout);
        } else {
                assoc_data->timeout_started = false;
        }
@@ -3524,7 +3450,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
-       mutex_lock(&ifmgd->mtx);
+       sdata_lock(sdata);
 
        if (ifmgd->status_received) {
                __le16 fc = ifmgd->status_fc;
@@ -3536,7 +3462,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
                        if (status_acked) {
                                ifmgd->auth_data->timeout =
                                        jiffies + IEEE80211_AUTH_TIMEOUT_SHORT;
-                               run_again(ifmgd, ifmgd->auth_data->timeout);
+                               run_again(sdata, ifmgd->auth_data->timeout);
                        } else {
                                ifmgd->auth_data->timeout = jiffies - 1;
                        }
@@ -3547,7 +3473,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
                        if (status_acked) {
                                ifmgd->assoc_data->timeout =
                                        jiffies + IEEE80211_ASSOC_TIMEOUT_SHORT;
-                               run_again(ifmgd, ifmgd->assoc_data->timeout);
+                               run_again(sdata, ifmgd->assoc_data->timeout);
                        } else {
                                ifmgd->assoc_data->timeout = jiffies - 1;
                        }
@@ -3570,12 +3496,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
 
                        ieee80211_destroy_auth_data(sdata, false);
 
-                       mutex_unlock(&ifmgd->mtx);
                        cfg80211_send_auth_timeout(sdata->dev, bssid);
-                       mutex_lock(&ifmgd->mtx);
                }
        } else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started)
-               run_again(ifmgd, ifmgd->auth_data->timeout);
+               run_again(sdata, ifmgd->auth_data->timeout);
 
        if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started &&
            time_after(jiffies, ifmgd->assoc_data->timeout)) {
@@ -3588,12 +3512,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
 
                        ieee80211_destroy_assoc_data(sdata, false);
 
-                       mutex_unlock(&ifmgd->mtx);
                        cfg80211_send_assoc_timeout(sdata->dev, bssid);
-                       mutex_lock(&ifmgd->mtx);
                }
        } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started)
-               run_again(ifmgd, ifmgd->assoc_data->timeout);
+               run_again(sdata, ifmgd->assoc_data->timeout);
 
        if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
                            IEEE80211_STA_CONNECTION_POLL) &&
@@ -3627,7 +3549,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
                                        false);
                        }
                } else if (time_is_after_jiffies(ifmgd->probe_timeout))
-                       run_again(ifmgd, ifmgd->probe_timeout);
+                       run_again(sdata, ifmgd->probe_timeout);
                else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
                        mlme_dbg(sdata,
                                 "Failed to send nullfunc to AP %pM after %dms, disconnecting\n",
@@ -3656,7 +3578,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
                }
        }
 
-       mutex_unlock(&ifmgd->mtx);
+       sdata_unlock(sdata);
 }
 
 static void ieee80211_sta_bcn_mon_timer(unsigned long data)
@@ -3717,9 +3639,9 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
-       mutex_lock(&ifmgd->mtx);
+       sdata_lock(sdata);
        if (!ifmgd->associated) {
-               mutex_unlock(&ifmgd->mtx);
+               sdata_unlock(sdata);
                return;
        }
 
@@ -3730,10 +3652,10 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
                                              ifmgd->associated->bssid,
                                              WLAN_REASON_UNSPECIFIED,
                                              true);
-               mutex_unlock(&ifmgd->mtx);
+               sdata_unlock(sdata);
                return;
        }
-       mutex_unlock(&ifmgd->mtx);
+       sdata_unlock(sdata);
 }
 #endif
 
@@ -3765,8 +3687,6 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
        ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len;
        ifmgd->p2p_noa_index = -1;
 
-       mutex_init(&ifmgd->mtx);
-
        if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)
                ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC;
        else
@@ -4122,8 +4042,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 
        /* try to authenticate/probe */
 
-       mutex_lock(&ifmgd->mtx);
-
        if ((ifmgd->auth_data && !ifmgd->auth_data->done) ||
            ifmgd->assoc_data) {
                err = -EBUSY;
@@ -4143,8 +4061,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
                                       WLAN_REASON_UNSPECIFIED,
                                       false, frame_buf);
 
-               __cfg80211_send_deauth(sdata->dev, frame_buf,
-                                      sizeof(frame_buf));
+               cfg80211_send_deauth(sdata->dev, frame_buf,
+                                    sizeof(frame_buf));
        }
 
        sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
@@ -4161,8 +4079,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 
        /* hold our own reference */
        cfg80211_ref_bss(local->hw.wiphy, auth_data->bss);
-       err = 0;
-       goto out_unlock;
+       return 0;
 
  err_clear:
        memset(ifmgd->bssid, 0, ETH_ALEN);
@@ -4170,9 +4087,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
        ifmgd->auth_data = NULL;
  err_free:
        kfree(auth_data);
- out_unlock:
-       mutex_unlock(&ifmgd->mtx);
-
        return err;
 }
 
@@ -4203,8 +4117,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
        assoc_data->ssid_len = ssidie[1];
        rcu_read_unlock();
 
-       mutex_lock(&ifmgd->mtx);
-
        if (ifmgd->associated) {
                u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
 
@@ -4212,8 +4124,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
                                       WLAN_REASON_UNSPECIFIED,
                                       false, frame_buf);
 
-               __cfg80211_send_deauth(sdata->dev, frame_buf,
-                                      sizeof(frame_buf));
+               cfg80211_send_deauth(sdata->dev, frame_buf,
+                                    sizeof(frame_buf));
        }
 
        if (ifmgd->auth_data && !ifmgd->auth_data->done) {
@@ -4407,7 +4319,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
        }
        rcu_read_unlock();
 
-       run_again(ifmgd, assoc_data->timeout);
+       run_again(sdata, assoc_data->timeout);
 
        if (bss->corrupt_data) {
                char *corrupt_type = "data";
@@ -4423,17 +4335,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
                           corrupt_type);
        }
 
-       err = 0;
-       goto out;
+       return 0;
  err_clear:
        memset(ifmgd->bssid, 0, ETH_ALEN);
        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
        ifmgd->assoc_data = NULL;
  err_free:
        kfree(assoc_data);
- out:
-       mutex_unlock(&ifmgd->mtx);
-
        return err;
 }
 
@@ -4445,8 +4353,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
        bool tx = !req->local_state_change;
        bool report_frame = false;
 
-       mutex_lock(&ifmgd->mtx);
-
        sdata_info(sdata,
                   "deauthenticating from %pM by local choice (reason=%d)\n",
                   req->bssid, req->reason_code);
@@ -4458,7 +4364,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
                                               req->reason_code, tx,
                                               frame_buf);
                ieee80211_destroy_auth_data(sdata, false);
-               mutex_unlock(&ifmgd->mtx);
 
                report_frame = true;
                goto out;
@@ -4470,12 +4375,11 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
                                       req->reason_code, tx, frame_buf);
                report_frame = true;
        }
-       mutex_unlock(&ifmgd->mtx);
 
  out:
        if (report_frame)
-               __cfg80211_send_deauth(sdata->dev, frame_buf,
-                                      IEEE80211_DEAUTH_FRAME_LEN);
+               cfg80211_send_deauth(sdata->dev, frame_buf,
+                                    IEEE80211_DEAUTH_FRAME_LEN);
 
        return 0;
 }
@@ -4487,18 +4391,14 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
        u8 bssid[ETH_ALEN];
        u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
 
-       mutex_lock(&ifmgd->mtx);
-
        /*
         * cfg80211 should catch this ... but it's racy since
         * we can receive a disassoc frame, process it, hand it
         * to cfg80211 while that's in a locked section already
         * trying to tell us that the user wants to disconnect.
         */
-       if (ifmgd->associated != req->bss) {
-               mutex_unlock(&ifmgd->mtx);
+       if (ifmgd->associated != req->bss)
                return -ENOLINK;
-       }
 
        sdata_info(sdata,
                   "disassociating from %pM by local choice (reason=%d)\n",
@@ -4508,10 +4408,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
        ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC,
                               req->reason_code, !req->local_state_change,
                               frame_buf);
-       mutex_unlock(&ifmgd->mtx);
 
-       __cfg80211_send_disassoc(sdata->dev, frame_buf,
-                                IEEE80211_DEAUTH_FRAME_LEN);
+       cfg80211_send_disassoc(sdata->dev, frame_buf,
+                              IEEE80211_DEAUTH_FRAME_LEN);
 
        return 0;
 }
@@ -4531,13 +4430,13 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
        cancel_work_sync(&ifmgd->csa_connection_drop_work);
        cancel_work_sync(&ifmgd->chswitch_work);
 
-       mutex_lock(&ifmgd->mtx);
+       sdata_lock(sdata);
        if (ifmgd->assoc_data)
                ieee80211_destroy_assoc_data(sdata, false);
        if (ifmgd->auth_data)
                ieee80211_destroy_auth_data(sdata, false);
        del_timer_sync(&ifmgd->timer);
-       mutex_unlock(&ifmgd->mtx);
+       sdata_unlock(sdata);
 }
 
 void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,