Merge wireless into wireless-next
[linux-2.6-microblaze.git] / net / mac80211 / cfg.c
index e7ac246..5cec0c2 100644 (file)
@@ -214,6 +214,8 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
        struct sta_info *sta;
        int ret;
 
+       lockdep_assert_wiphy(local->hw.wiphy);
+
        ret = ieee80211_if_change_type(sdata, type);
        if (ret)
                return ret;
@@ -235,12 +237,10 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
                if (!ifmgd->associated)
                        return 0;
 
-               mutex_lock(&local->sta_mtx);
                sta = sta_info_get(sdata, sdata->deflink.u.mgd.bssid);
                if (sta)
                        drv_sta_set_4addr(local, sdata, &sta->sta,
                                          params->use_4addr);
-               mutex_unlock(&local->sta_mtx);
 
                if (params->use_4addr)
                        ieee80211_send_4addr_nullfunc(local, sdata);
@@ -261,9 +261,9 @@ static int ieee80211_start_p2p_device(struct wiphy *wiphy,
        struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
        int ret;
 
-       mutex_lock(&sdata->local->chanctx_mtx);
+       lockdep_assert_wiphy(sdata->local->hw.wiphy);
+
        ret = ieee80211_check_combinations(sdata, NULL, 0, 0);
-       mutex_unlock(&sdata->local->chanctx_mtx);
        if (ret < 0)
                return ret;
 
@@ -283,9 +283,9 @@ static int ieee80211_start_nan(struct wiphy *wiphy,
        struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
        int ret;
 
-       mutex_lock(&sdata->local->chanctx_mtx);
+       lockdep_assert_wiphy(sdata->local->hw.wiphy);
+
        ret = ieee80211_check_combinations(sdata, NULL, 0, 0);
-       mutex_unlock(&sdata->local->chanctx_mtx);
        if (ret < 0)
                return ret;
 
@@ -452,13 +452,11 @@ static int ieee80211_set_tx(struct ieee80211_sub_if_data *sdata,
        if (sta->ptk_idx == key_idx)
                return 0;
 
-       mutex_lock(&local->key_mtx);
-       key = key_mtx_dereference(local, sta->ptk[key_idx]);
+       key = wiphy_dereference(local->hw.wiphy, sta->ptk[key_idx]);
 
        if (key && key->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX)
                ret = ieee80211_set_tx_key(key);
 
-       mutex_unlock(&local->key_mtx);
        return ret;
 }
 
@@ -474,6 +472,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_key *key;
        int err;
 
+       lockdep_assert_wiphy(local->hw.wiphy);
+
        if (!ieee80211_sdata_running(sdata))
                return -ENETDOWN;
 
@@ -510,8 +510,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        if (params->mode == NL80211_KEY_NO_TX)
                key->conf.flags |= IEEE80211_KEY_FLAG_NO_AUTO_TX;
 
-       mutex_lock(&local->sta_mtx);
-
        if (mac_addr) {
                sta = sta_info_get_bss(sdata, mac_addr);
                /*
@@ -526,8 +524,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
                 */
                if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) {
                        ieee80211_key_free_unused(key);
-                       err = -ENOENT;
-                       goto out_unlock;
+                       return -ENOENT;
                }
        }
 
@@ -566,9 +563,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        }
 
        err = ieee80211_key_link(key, link, sta);
-
- out_unlock:
-       mutex_unlock(&local->sta_mtx);
+       /* KRACK protection, shouldn't happen but just silently accept key */
+       if (err == -EALREADY)
+               err = 0;
 
        return err;
 }
@@ -582,8 +579,7 @@ ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata, int link_id,
        struct ieee80211_key *key;
 
        if (link_id >= 0) {
-               link = rcu_dereference_check(sdata->link[link_id],
-                                            lockdep_is_held(&sdata->wdev.mtx));
+               link = sdata_dereference(sdata->link[link_id], sdata);
                if (!link)
                        return NULL;
        }
@@ -598,7 +594,7 @@ ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata, int link_id,
 
                if (link_id >= 0) {
                        link_sta = rcu_dereference_check(sta->link[link_id],
-                                                        lockdep_is_held(&local->sta_mtx));
+                                                        lockdep_is_held(&local->hw.wiphy->mtx));
                        if (!link_sta)
                                return NULL;
                } else {
@@ -606,30 +602,29 @@ ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata, int link_id,
                }
 
                if (pairwise && key_idx < NUM_DEFAULT_KEYS)
-                       return rcu_dereference_check_key_mtx(local,
-                                                            sta->ptk[key_idx]);
+                       return wiphy_dereference(local->hw.wiphy,
+                                                sta->ptk[key_idx]);
 
                if (!pairwise &&
                    key_idx < NUM_DEFAULT_KEYS +
                              NUM_DEFAULT_MGMT_KEYS +
                              NUM_DEFAULT_BEACON_KEYS)
-                       return rcu_dereference_check_key_mtx(local,
-                                                            link_sta->gtk[key_idx]);
+                       return wiphy_dereference(local->hw.wiphy,
+                                                link_sta->gtk[key_idx]);
 
                return NULL;
        }
 
        if (pairwise && key_idx < NUM_DEFAULT_KEYS)
-               return rcu_dereference_check_key_mtx(local,
-                                                    sdata->keys[key_idx]);
+               return wiphy_dereference(local->hw.wiphy, sdata->keys[key_idx]);
 
-       key = rcu_dereference_check_key_mtx(local, link->gtk[key_idx]);
+       key = wiphy_dereference(local->hw.wiphy, link->gtk[key_idx]);
        if (key)
                return key;
 
        /* or maybe it was a WEP key */
        if (key_idx < NUM_DEFAULT_KEYS)
-               return rcu_dereference_check_key_mtx(local, sdata->keys[key_idx]);
+               return wiphy_dereference(local->hw.wiphy, sdata->keys[key_idx]);
 
        return NULL;
 }
@@ -641,25 +636,16 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_key *key;
-       int ret;
 
-       mutex_lock(&local->sta_mtx);
-       mutex_lock(&local->key_mtx);
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        key = ieee80211_lookup_key(sdata, link_id, key_idx, pairwise, mac_addr);
-       if (!key) {
-               ret = -ENOENT;
-               goto out_unlock;
-       }
+       if (!key)
+               return -ENOENT;
 
        ieee80211_key_free(key, sdata->vif.type == NL80211_IFTYPE_STATION);
 
-       ret = 0;
- out_unlock:
-       mutex_unlock(&local->key_mtx);
-       mutex_unlock(&local->sta_mtx);
-
-       return ret;
+       return 0;
 }
 
 static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
@@ -830,15 +816,11 @@ void sta_set_rate_info_tx(struct sta_info *sta,
                rinfo->nss = ieee80211_rate_get_vht_nss(rate);
        } else {
                struct ieee80211_supported_band *sband;
-               int shift = ieee80211_vif_get_shift(&sta->sdata->vif);
-               u16 brate;
 
                sband = ieee80211_get_sband(sta->sdata);
                WARN_ON_ONCE(sband && !sband->bitrates);
-               if (sband && sband->bitrates) {
-                       brate = sband->bitrates[rate->idx].bitrate;
-                       rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
-               }
+               if (sband && sband->bitrates)
+                       rinfo->legacy = sband->bitrates[rate->idx].bitrate;
        }
        if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
                rinfo->bw = RATE_INFO_BW_40;
@@ -860,7 +842,7 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
        struct sta_info *sta;
        int ret = -ENOENT;
 
-       mutex_lock(&local->sta_mtx);
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        sta = sta_info_get_by_idx(sdata, idx);
        if (sta) {
@@ -869,8 +851,6 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
                sta_set_sinfo(sta, sinfo, true);
        }
 
-       mutex_unlock(&local->sta_mtx);
-
        return ret;
 }
 
@@ -890,7 +870,7 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
        struct sta_info *sta;
        int ret = -ENOENT;
 
-       mutex_lock(&local->sta_mtx);
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        sta = sta_info_get_bss(sdata, mac);
        if (sta) {
@@ -898,8 +878,6 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
                sta_set_sinfo(sta, sinfo, true);
        }
 
-       mutex_unlock(&local->sta_mtx);
-
        return ret;
 }
 
@@ -910,6 +888,8 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
        struct ieee80211_sub_if_data *sdata;
        int ret = 0;
 
+       lockdep_assert_wiphy(local->hw.wiphy);
+
        if (cfg80211_chandef_identical(&local->monitor_chandef, chandef))
                return 0;
 
@@ -917,22 +897,16 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
                sdata = wiphy_dereference(local->hw.wiphy,
                                          local->monitor_sdata);
                if (sdata) {
-                       sdata_lock(sdata);
-                       mutex_lock(&local->mtx);
                        ieee80211_link_release_channel(&sdata->deflink);
                        ret = ieee80211_link_use_channel(&sdata->deflink,
                                                         chandef,
                                                         IEEE80211_CHANCTX_EXCLUSIVE);
-                       mutex_unlock(&local->mtx);
-                       sdata_unlock(sdata);
                }
        } else {
-               mutex_lock(&local->mtx);
                if (local->open_count == local->monitors) {
                        local->_oper_chandef = *chandef;
                        ieee80211_hw_config(local, 0);
                }
-               mutex_unlock(&local->mtx);
        }
 
        if (ret == 0)
@@ -984,25 +958,29 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata,
        struct fils_discovery_data *new, *old = NULL;
        struct ieee80211_fils_discovery *fd;
 
-       if (!params->tmpl || !params->tmpl_len)
-               return -EINVAL;
+       if (!params->update)
+               return 0;
 
        fd = &link_conf->fils_discovery;
        fd->min_interval = params->min_interval;
        fd->max_interval = params->max_interval;
 
        old = sdata_dereference(link->u.ap.fils_discovery, sdata);
-       new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL);
-       if (!new)
-               return -ENOMEM;
-       new->len = params->tmpl_len;
-       memcpy(new->data, params->tmpl, params->tmpl_len);
-       rcu_assign_pointer(link->u.ap.fils_discovery, new);
-
        if (old)
                kfree_rcu(old, rcu_head);
 
-       return 0;
+       if (params->tmpl && params->tmpl_len) {
+               new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL);
+               if (!new)
+                       return -ENOMEM;
+               new->len = params->tmpl_len;
+               memcpy(new->data, params->tmpl, params->tmpl_len);
+               rcu_assign_pointer(link->u.ap.fils_discovery, new);
+       } else {
+               RCU_INIT_POINTER(link->u.ap.fils_discovery, NULL);
+       }
+
+       return BSS_CHANGED_FILS_DISCOVERY;
 }
 
 static int
@@ -1013,23 +991,27 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata,
 {
        struct unsol_bcast_probe_resp_data *new, *old = NULL;
 
-       if (!params->tmpl || !params->tmpl_len)
-               return -EINVAL;
+       if (!params->update)
+               return 0;
 
-       old = sdata_dereference(link->u.ap.unsol_bcast_probe_resp, sdata);
-       new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL);
-       if (!new)
-               return -ENOMEM;
-       new->len = params->tmpl_len;
-       memcpy(new->data, params->tmpl, params->tmpl_len);
-       rcu_assign_pointer(link->u.ap.unsol_bcast_probe_resp, new);
+       link_conf->unsol_bcast_probe_resp_interval = params->interval;
 
+       old = sdata_dereference(link->u.ap.unsol_bcast_probe_resp, sdata);
        if (old)
                kfree_rcu(old, rcu_head);
 
-       link_conf->unsol_bcast_probe_resp_interval = params->interval;
+       if (params->tmpl && params->tmpl_len) {
+               new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL);
+               if (!new)
+                       return -ENOMEM;
+               new->len = params->tmpl_len;
+               memcpy(new->data, params->tmpl, params->tmpl_len);
+               rcu_assign_pointer(link->u.ap.unsol_bcast_probe_resp, new);
+       } else {
+               RCU_INIT_POINTER(link->u.ap.unsol_bcast_probe_resp, NULL);
+       }
 
-       return 0;
+       return BSS_CHANGED_UNSOL_BCAST_PROBE_RESP;
 }
 
 static int ieee80211_set_ftm_responder_params(
@@ -1275,6 +1257,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_link_data *link;
        struct ieee80211_bss_conf *link_conf;
 
+       lockdep_assert_wiphy(local->hw.wiphy);
+
        link = sdata_dereference(sdata->link[link_id], sdata);
        if (!link)
                return -ENOLINK;
@@ -1384,12 +1368,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
                        return err;
        }
 
-       mutex_lock(&local->mtx);
        err = ieee80211_link_use_channel(link, &params->chandef,
                                         IEEE80211_CHANCTX_SHARED);
        if (!err)
                ieee80211_link_copy_chanctx_to_vlans(link, false);
-       mutex_unlock(&local->mtx);
        if (err) {
                link_conf->beacon_int = prev_beacon_int;
                return err;
@@ -1460,23 +1442,18 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
        if (err < 0)
                goto error;
 
-       if (params->fils_discovery.max_interval) {
-               err = ieee80211_set_fils_discovery(sdata,
-                                                  &params->fils_discovery,
-                                                  link, link_conf);
-               if (err < 0)
-                       goto error;
-               changed |= BSS_CHANGED_FILS_DISCOVERY;
-       }
+       err = ieee80211_set_fils_discovery(sdata, &params->fils_discovery,
+                                          link, link_conf);
+       if (err < 0)
+               goto error;
+       changed |= err;
 
-       if (params->unsol_bcast_probe_resp.interval) {
-               err = ieee80211_set_unsol_bcast_probe_resp(sdata,
-                                                          &params->unsol_bcast_probe_resp,
-                                                          link, link_conf);
-               if (err < 0)
-                       goto error;
-               changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP;
-       }
+       err = ieee80211_set_unsol_bcast_probe_resp(sdata,
+                                                  &params->unsol_bcast_probe_resp,
+                                                  link, link_conf);
+       if (err < 0)
+               goto error;
+       changed |= err;
 
        err = drv_start_ap(sdata->local, sdata, link_conf);
        if (err) {
@@ -1500,26 +1477,26 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
        return 0;
 
 error:
-       mutex_lock(&local->mtx);
        ieee80211_link_release_channel(link);
-       mutex_unlock(&local->mtx);
 
        return err;
 }
 
 static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
-                                  struct cfg80211_beacon_data *params)
+                                  struct cfg80211_ap_update *params)
+
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_link_data *link;
+       struct cfg80211_beacon_data *beacon = &params->beacon;
        struct beacon_data *old;
        int err;
        struct ieee80211_bss_conf *link_conf;
        u64 changed = 0;
 
-       sdata_assert_lock(sdata);
+       lockdep_assert_wiphy(wiphy);
 
-       link = sdata_dereference(sdata->link[params->link_id], sdata);
+       link = sdata_dereference(sdata->link[beacon->link_id], sdata);
        if (!link)
                return -ENOLINK;
 
@@ -1535,14 +1512,27 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
        if (!old)
                return -ENOENT;
 
-       err = ieee80211_assign_beacon(sdata, link, params, NULL, NULL,
+       err = ieee80211_assign_beacon(sdata, link, beacon, NULL, NULL,
                                      &changed);
        if (err < 0)
                return err;
 
-       if (params->he_bss_color_valid &&
-           params->he_bss_color.enabled != link_conf->he_bss_color.enabled) {
-               link_conf->he_bss_color.enabled = params->he_bss_color.enabled;
+       err = ieee80211_set_fils_discovery(sdata, &params->fils_discovery,
+                                          link, link_conf);
+       if (err < 0)
+               return err;
+       changed |= err;
+
+       err = ieee80211_set_unsol_bcast_probe_resp(sdata,
+                                                  &params->unsol_bcast_probe_resp,
+                                                  link, link_conf);
+       if (err < 0)
+               return err;
+       changed |= err;
+
+       if (beacon->he_bss_color_valid &&
+           beacon->he_bss_color.enabled != link_conf->he_bss_color.enabled) {
+               link_conf->he_bss_color.enabled = beacon->he_bss_color.enabled;
                changed |= BSS_CHANGED_HE_BSS_COLOR;
        }
 
@@ -1576,7 +1566,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
                sdata_dereference(sdata->link[link_id], sdata);
        struct ieee80211_bss_conf *link_conf = link->conf;
 
-       sdata_assert_lock(sdata);
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        old_beacon = sdata_dereference(link->u.ap.beacon, sdata);
        if (!old_beacon)
@@ -1590,7 +1580,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
                                  sdata);
 
        /* abort any running channel switch or color change */
-       mutex_lock(&local->mtx);
        link_conf->csa_active = false;
        link_conf->color_change_active = false;
        if (link->csa_block_tx) {
@@ -1599,8 +1588,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
                link->csa_block_tx = false;
        }
 
-       mutex_unlock(&local->mtx);
-
        ieee80211_free_next_beacon(link);
 
        /* turn off carrier for this interface and dependent VLANs */
@@ -1643,7 +1630,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
 
        if (sdata->wdev.cac_started) {
                chandef = link_conf->chandef;
-               cancel_delayed_work_sync(&link->dfs_cac_timer_work);
+               wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work);
                cfg80211_cac_event(sdata->dev, &chandef,
                                   NL80211_RADAR_CAC_ABORTED,
                                   GFP_KERNEL);
@@ -1655,10 +1642,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
        local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf);
        ieee80211_purge_tx_queue(&local->hw, &sdata->u.ap.ps.bc_buf);
 
-       mutex_lock(&local->mtx);
        ieee80211_link_copy_chanctx_to_vlans(link, true);
        ieee80211_link_release_channel(link);
-       mutex_unlock(&local->mtx);
 
        return 0;
 }
@@ -1800,7 +1785,7 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
                sdata_dereference(sdata->link[link_id], sdata);
        struct link_sta_info *link_sta =
                rcu_dereference_protected(sta->link[link_id],
-                                         lockdep_is_held(&local->sta_mtx));
+                                         lockdep_is_held(&local->hw.wiphy->mtx));
 
        /*
         * If there are no changes, then accept a link that doesn't exist,
@@ -1857,7 +1842,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
        /* VHT can override some HT caps such as the A-MSDU max length */
        if (params->vht_capa)
                ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
-                                                   params->vht_capa, link_sta);
+                                                   params->vht_capa, NULL,
+                                                   link_sta);
 
        if (params->he_capa)
                ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
@@ -2034,6 +2020,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_sub_if_data *sdata;
        int err;
 
+       lockdep_assert_wiphy(local->hw.wiphy);
+
        if (params->vlan) {
                sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
 
@@ -2077,9 +2065,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
         * visible yet), sta_apply_parameters (and inner functions) require
         * the mutex due to other paths.
         */
-       mutex_lock(&local->sta_mtx);
        err = sta_apply_parameters(local, sta, params);
-       mutex_unlock(&local->sta_mtx);
        if (err) {
                sta_info_free(local, sta);
                return err;
@@ -2122,13 +2108,11 @@ static int ieee80211_change_station(struct wiphy *wiphy,
        enum cfg80211_station_type statype;
        int err;
 
-       mutex_lock(&local->sta_mtx);
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        sta = sta_info_get_bss(sdata, mac);
-       if (!sta) {
-               err = -ENOENT;
-               goto out_err;
-       }
+       if (!sta)
+               return -ENOENT;
 
        switch (sdata->vif.type) {
        case NL80211_IFTYPE_MESH_POINT:
@@ -2158,22 +2142,19 @@ static int ieee80211_change_station(struct wiphy *wiphy,
                        statype = CFG80211_STA_AP_CLIENT_UNASSOC;
                break;
        default:
-               err = -EOPNOTSUPP;
-               goto out_err;
+               return -EOPNOTSUPP;
        }
 
        err = cfg80211_check_station_change(wiphy, params, statype);
        if (err)
-               goto out_err;
+               return err;
 
        if (params->vlan && params->vlan != sta->sdata->dev) {
                vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
 
                if (params->vlan->ieee80211_ptr->use_4addr) {
-                       if (vlansdata->u.vlan.sta) {
-                               err = -EBUSY;
-                               goto out_err;
-                       }
+                       if (vlansdata->u.vlan.sta)
+                               return -EBUSY;
 
                        rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
                        __ieee80211_check_fast_rx_iface(vlansdata);
@@ -2199,18 +2180,9 @@ static int ieee80211_change_station(struct wiphy *wiphy,
                }
        }
 
-       /* we use sta_info_get_bss() so this might be different */
-       if (sdata != sta->sdata) {
-               mutex_lock_nested(&sta->sdata->wdev.mtx, 1);
-               err = sta_apply_parameters(local, sta, params);
-               mutex_unlock(&sta->sdata->wdev.mtx);
-       } else {
-               err = sta_apply_parameters(local, sta, params);
-       }
+       err = sta_apply_parameters(local, sta, params);
        if (err)
-               goto out_err;
-
-       mutex_unlock(&local->sta_mtx);
+               return err;
 
        if (sdata->vif.type == NL80211_IFTYPE_STATION &&
            params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
@@ -2219,9 +2191,6 @@ static int ieee80211_change_station(struct wiphy *wiphy,
        }
 
        return 0;
-out_err:
-       mutex_unlock(&local->sta_mtx);
-       return err;
 }
 
 #ifdef CONFIG_MAC80211_MESH
@@ -2634,6 +2603,8 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
        int err;
 
+       lockdep_assert_wiphy(sdata->local->hw.wiphy);
+
        memcpy(&ifmsh->mshcfg, conf, sizeof(struct mesh_config));
        err = copy_mesh_setup(ifmsh, setup);
        if (err)
@@ -2645,10 +2616,8 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
        sdata->deflink.smps_mode = IEEE80211_SMPS_OFF;
        sdata->deflink.needed_rx_chains = sdata->local->rx_chains;
 
-       mutex_lock(&sdata->local->mtx);
        err = ieee80211_link_use_channel(&sdata->deflink, &setup->chandef,
                                         IEEE80211_CHANCTX_SHARED);
-       mutex_unlock(&sdata->local->mtx);
        if (err)
                return err;
 
@@ -2659,11 +2628,11 @@ static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
+       lockdep_assert_wiphy(sdata->local->hw.wiphy);
+
        ieee80211_stop_mesh(sdata);
-       mutex_lock(&sdata->local->mtx);
        ieee80211_link_release_channel(&sdata->deflink);
        kfree(sdata->u.mesh.ie);
-       mutex_unlock(&sdata->local->mtx);
 
        return 0;
 }
@@ -3021,6 +2990,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
        bool update_txp_type = false;
        bool has_monitor = false;
 
+       lockdep_assert_wiphy(local->hw.wiphy);
+
        if (wdev) {
                sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
 
@@ -3068,7 +3039,6 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
                break;
        }
 
-       mutex_lock(&local->iflist_mtx);
        list_for_each_entry(sdata, &local->interfaces, list) {
                if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
                        has_monitor = true;
@@ -3084,7 +3054,6 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
                        continue;
                ieee80211_recalc_txpower(sdata, update_txp_type);
        }
-       mutex_unlock(&local->iflist_mtx);
 
        if (has_monitor) {
                sdata = wiphy_dereference(local->hw.wiphy,
@@ -3117,6 +3086,10 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy,
        else
                *dbm = sdata->vif.bss_conf.txpower;
 
+       /* INT_MIN indicates no power level was set yet */
+       if (*dbm == INT_MIN)
+               return -EINVAL;
+
        return 0;
 }
 
@@ -3173,11 +3146,15 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
        struct sta_info *sta;
        bool tdls_peer_found = false;
 
-       lockdep_assert_held(&sdata->wdev.mtx);
+       lockdep_assert_wiphy(sdata->local->hw.wiphy);
 
        if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION))
                return -EINVAL;
 
+       if (ieee80211_vif_is_mld(&sdata->vif) &&
+           !(sdata->vif.active_links & BIT(link->link_id)))
+               return 0;
+
        old_req = link->u.mgd.req_smps;
        link->u.mgd.req_smps = smps_mode;
 
@@ -3194,7 +3171,7 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
            link->conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
                return 0;
 
-       ap = link->u.mgd.bssid;
+       ap = sdata->vif.cfg.ap_addr;
 
        rcu_read_lock();
        list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
@@ -3216,7 +3193,9 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
 
        /* send SM PS frame to AP */
        err = ieee80211_send_smps_action(sdata, smps_mode,
-                                        ap, ap);
+                                        ap, ap,
+                                        ieee80211_vif_is_mld(&sdata->vif) ?
+                                        link->link_id : -1);
        if (err)
                link->u.mgd.req_smps = old_req;
        else if (smps_mode != IEEE80211_SMPS_OFF && tdls_peer_found)
@@ -3246,7 +3225,6 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
        local->dynamic_ps_forced_timeout = timeout;
 
        /* no change, but if automatic follow powersave */
-       sdata_lock(sdata);
        for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
                struct ieee80211_link_data *link;
 
@@ -3257,7 +3235,6 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
                __ieee80211_request_smps_mgd(sdata, link,
                                             link->u.mgd.req_smps);
        }
-       sdata_unlock(sdata);
 
        if (ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS))
                ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
@@ -3403,7 +3380,8 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
        struct ieee80211_local *local = sdata->local;
        int err;
 
-       mutex_lock(&local->mtx);
+       lockdep_assert_wiphy(local->hw.wiphy);
+
        if (!list_empty(&local->roc_list) || local->scanning) {
                err = -EBUSY;
                goto out_unlock;
@@ -3418,12 +3396,10 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
        if (err)
                goto out_unlock;
 
-       ieee80211_queue_delayed_work(&sdata->local->hw,
-                                    &sdata->deflink.dfs_cac_timer_work,
-                                    msecs_to_jiffies(cac_time_ms));
+       wiphy_delayed_work_queue(wiphy, &sdata->deflink.dfs_cac_timer_work,
+                                msecs_to_jiffies(cac_time_ms));
 
  out_unlock:
-       mutex_unlock(&local->mtx);
        return err;
 }
 
@@ -3433,20 +3409,21 @@ static void ieee80211_end_cac(struct wiphy *wiphy,
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
 
-       mutex_lock(&local->mtx);
+       lockdep_assert_wiphy(local->hw.wiphy);
+
        list_for_each_entry(sdata, &local->interfaces, list) {
                /* it might be waiting for the local->mtx, but then
                 * by the time it gets it, sdata->wdev.cac_started
                 * will no longer be true
                 */
-               cancel_delayed_work(&sdata->deflink.dfs_cac_timer_work);
+               wiphy_delayed_work_cancel(wiphy,
+                                         &sdata->deflink.dfs_cac_timer_work);
 
                if (sdata->wdev.cac_started) {
                        ieee80211_link_release_channel(&sdata->deflink);
                        sdata->wdev.cac_started = false;
                }
        }
-       mutex_unlock(&local->mtx);
 }
 
 static struct cfg80211_beacon_data *
@@ -3578,11 +3555,11 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif)
                        if (iter == sdata || iter->vif.mbssid_tx_vif != vif)
                                continue;
 
-                       ieee80211_queue_work(&iter->local->hw,
-                                            &iter->deflink.csa_finalize_work);
+                       wiphy_work_queue(iter->local->hw.wiphy,
+                                        &iter->deflink.csa_finalize_work);
                }
        }
-       ieee80211_queue_work(&local->hw, &sdata->deflink.csa_finalize_work);
+       wiphy_work_queue(local->hw.wiphy, &sdata->deflink.csa_finalize_work);
 
        rcu_read_unlock();
 }
@@ -3638,21 +3615,14 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
        return 0;
 }
 
-static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
+static int __ieee80211_csa_finalize(struct ieee80211_link_data *link_data)
 {
+       struct ieee80211_sub_if_data *sdata = link_data->sdata;
        struct ieee80211_local *local = sdata->local;
        u64 changed = 0;
        int err;
 
-       sdata_assert_lock(sdata);
-       lockdep_assert_held(&local->mtx);
-       lockdep_assert_held(&local->chanctx_mtx);
-
-       if (sdata->vif.bss_conf.eht_puncturing != sdata->vif.bss_conf.csa_punct_bitmap) {
-               sdata->vif.bss_conf.eht_puncturing =
-                                       sdata->vif.bss_conf.csa_punct_bitmap;
-               changed |= BSS_CHANGED_EHT_PUNCTURING;
-       }
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        /*
         * using reservation isn't immediate as it may be deferred until later
@@ -3661,20 +3631,20 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
         * completed successfully
         */
 
-       if (sdata->deflink.reserved_chanctx) {
+       if (link_data->reserved_chanctx) {
                /*
                 * with multi-vif csa driver may call ieee80211_csa_finish()
                 * many times while waiting for other interfaces to use their
                 * reservations
                 */
-               if (sdata->deflink.reserved_ready)
+               if (link_data->reserved_ready)
                        return 0;
 
                return ieee80211_link_use_reserved_context(&sdata->deflink);
        }
 
-       if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef,
-                                       &sdata->deflink.csa_chandef))
+       if (!cfg80211_chandef_identical(&link_data->conf->chandef,
+                                       &link_data->csa_chandef))
                return -EINVAL;
 
        sdata->vif.bss_conf.csa_active = false;
@@ -3683,57 +3653,59 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
        if (err)
                return err;
 
-       ieee80211_link_info_change_notify(sdata, &sdata->deflink, changed);
+       if (sdata->vif.bss_conf.eht_puncturing != sdata->vif.bss_conf.csa_punct_bitmap) {
+               sdata->vif.bss_conf.eht_puncturing =
+                                       sdata->vif.bss_conf.csa_punct_bitmap;
+               changed |= BSS_CHANGED_EHT_PUNCTURING;
+       }
 
-       if (sdata->deflink.csa_block_tx) {
+       ieee80211_link_info_change_notify(sdata, link_data, changed);
+
+       if (link_data->csa_block_tx) {
                ieee80211_wake_vif_queues(local, sdata,
                                          IEEE80211_QUEUE_STOP_REASON_CSA);
-               sdata->deflink.csa_block_tx = false;
+               link_data->csa_block_tx = false;
        }
 
-       err = drv_post_channel_switch(sdata);
+       err = drv_post_channel_switch(link_data);
        if (err)
                return err;
 
-       cfg80211_ch_switch_notify(sdata->dev, &sdata->deflink.csa_chandef, 0,
-                                 sdata->vif.bss_conf.eht_puncturing);
+       cfg80211_ch_switch_notify(sdata->dev, &link_data->csa_chandef,
+                                 link_data->link_id,
+                                 link_data->conf->eht_puncturing);
 
        return 0;
 }
 
-static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
+static void ieee80211_csa_finalize(struct ieee80211_link_data *link_data)
 {
-       if (__ieee80211_csa_finalize(sdata)) {
+       struct ieee80211_sub_if_data *sdata = link_data->sdata;
+
+       if (__ieee80211_csa_finalize(link_data)) {
                sdata_info(sdata, "failed to finalize CSA, disconnecting\n");
                cfg80211_stop_iface(sdata->local->hw.wiphy, &sdata->wdev,
                                    GFP_KERNEL);
        }
 }
 
-void ieee80211_csa_finalize_work(struct work_struct *work)
+void ieee80211_csa_finalize_work(struct wiphy *wiphy, struct wiphy_work *work)
 {
-       struct ieee80211_sub_if_data *sdata =
-               container_of(work, struct ieee80211_sub_if_data,
-                            deflink.csa_finalize_work);
+       struct ieee80211_link_data *link =
+               container_of(work, struct ieee80211_link_data, csa_finalize_work);
+       struct ieee80211_sub_if_data *sdata = link->sdata;
        struct ieee80211_local *local = sdata->local;
 
-       sdata_lock(sdata);
-       mutex_lock(&local->mtx);
-       mutex_lock(&local->chanctx_mtx);
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        /* AP might have been stopped while waiting for the lock. */
-       if (!sdata->vif.bss_conf.csa_active)
-               goto unlock;
+       if (!link->conf->csa_active)
+               return;
 
        if (!ieee80211_sdata_running(sdata))
-               goto unlock;
-
-       ieee80211_csa_finalize(sdata);
+               return;
 
-unlock:
-       mutex_unlock(&local->chanctx_mtx);
-       mutex_unlock(&local->mtx);
-       sdata_unlock(sdata);
+       ieee80211_csa_finalize(link);
 }
 
 static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
@@ -3889,8 +3861,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
        u64 changed = 0;
        int err;
 
-       sdata_assert_lock(sdata);
-       lockdep_assert_held(&local->mtx);
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        if (!list_empty(&local->roc_list) || local->scanning)
                return -EBUSY;
@@ -3906,9 +3877,8 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
        if (sdata->vif.bss_conf.csa_active)
                return -EBUSY;
 
-       mutex_lock(&local->chanctx_mtx);
        conf = rcu_dereference_protected(sdata->vif.bss_conf.chanctx_conf,
-                                        lockdep_is_held(&local->chanctx_mtx));
+                                        lockdep_is_held(&local->hw.wiphy->mtx));
        if (!conf) {
                err = -EBUSY;
                goto out;
@@ -3978,11 +3948,10 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
                drv_channel_switch_beacon(sdata, &params->chandef);
        } else {
                /* if the beacon didn't change, we can finalize immediately */
-               ieee80211_csa_finalize(sdata);
+               ieee80211_csa_finalize(&sdata->deflink);
        }
 
 out:
-       mutex_unlock(&local->chanctx_mtx);
        return err;
 }
 
@@ -3991,18 +3960,15 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
-       int err;
 
-       mutex_lock(&local->mtx);
-       err = __ieee80211_channel_switch(wiphy, dev, params);
-       mutex_unlock(&local->mtx);
+       lockdep_assert_wiphy(local->hw.wiphy);
 
-       return err;
+       return __ieee80211_channel_switch(wiphy, dev, params);
 }
 
 u64 ieee80211_mgmt_tx_cookie(struct ieee80211_local *local)
 {
-       lockdep_assert_held(&local->mtx);
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        local->roc_cookie_counter++;
 
@@ -4034,7 +4000,8 @@ int ieee80211_attach_ack_skb(struct ieee80211_local *local, struct sk_buff *skb,
                return -ENOMEM;
        }
 
-       IEEE80211_SKB_CB(skb)->ack_frame_id = id;
+       IEEE80211_SKB_CB(skb)->status_data_idr = 1;
+       IEEE80211_SKB_CB(skb)->status_data = id;
 
        *cookie = ieee80211_mgmt_tx_cookie(local);
        IEEE80211_SKB_CB(ack_skb)->ack.cookie = *cookie;
@@ -4084,11 +4051,17 @@ ieee80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
 static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
 {
        struct ieee80211_local *local = wiphy_priv(wiphy);
+       int ret;
 
        if (local->started)
                return -EOPNOTSUPP;
 
-       return drv_set_antenna(local, tx_ant, rx_ant);
+       ret = drv_set_antenna(local, tx_ant, rx_ant);
+       if (ret)
+               return ret;
+
+       local->rx_chains = hweight8(rx_ant);
+       return 0;
 }
 
 static int ieee80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant)
@@ -4130,22 +4103,23 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
        int ret;
 
        /* the lock is needed to assign the cookie later */
-       mutex_lock(&local->mtx);
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        rcu_read_lock();
+       sta = sta_info_get_bss(sdata, peer);
+       if (!sta) {
+               ret = -ENOLINK;
+               goto unlock;
+       }
+
+       qos = sta->sta.wme;
+
        chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
        if (WARN_ON(!chanctx_conf)) {
                ret = -EINVAL;
                goto unlock;
        }
        band = chanctx_conf->def.chan->band;
-       sta = sta_info_get_bss(sdata, peer);
-       if (sta) {
-               qos = sta->sta.wme;
-       } else {
-               ret = -ENOLINK;
-               goto unlock;
-       }
 
        if (qos) {
                fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
@@ -4200,7 +4174,6 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
        ret = 0;
 unlock:
        rcu_read_unlock();
-       mutex_unlock(&local->mtx);
 
        return ret;
 }
@@ -4558,7 +4531,8 @@ static int ieee80211_set_tid_config(struct wiphy *wiphy,
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct sta_info *sta;
-       int ret;
+
+       lockdep_assert_wiphy(sdata->local->hw.wiphy);
 
        if (!sdata->local->ops->set_tid_config)
                return -EOPNOTSUPP;
@@ -4566,17 +4540,11 @@ static int ieee80211_set_tid_config(struct wiphy *wiphy,
        if (!tid_conf->peer)
                return drv_set_tid_config(sdata->local, sdata, NULL, tid_conf);
 
-       mutex_lock(&sdata->local->sta_mtx);
        sta = sta_info_get_bss(sdata, tid_conf->peer);
-       if (!sta) {
-               mutex_unlock(&sdata->local->sta_mtx);
+       if (!sta)
                return -ENOENT;
-       }
-
-       ret = drv_set_tid_config(sdata->local, sdata, &sta->sta, tid_conf);
-       mutex_unlock(&sdata->local->sta_mtx);
 
-       return ret;
+       return drv_set_tid_config(sdata->local, sdata, &sta->sta, tid_conf);
 }
 
 static int ieee80211_reset_tid_config(struct wiphy *wiphy,
@@ -4585,7 +4553,8 @@ static int ieee80211_reset_tid_config(struct wiphy *wiphy,
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct sta_info *sta;
-       int ret;
+
+       lockdep_assert_wiphy(sdata->local->hw.wiphy);
 
        if (!sdata->local->ops->reset_tid_config)
                return -EOPNOTSUPP;
@@ -4593,17 +4562,11 @@ static int ieee80211_reset_tid_config(struct wiphy *wiphy,
        if (!peer)
                return drv_reset_tid_config(sdata->local, sdata, NULL, tids);
 
-       mutex_lock(&sdata->local->sta_mtx);
        sta = sta_info_get_bss(sdata, peer);
-       if (!sta) {
-               mutex_unlock(&sdata->local->sta_mtx);
+       if (!sta)
                return -ENOENT;
-       }
-
-       ret = drv_reset_tid_config(sdata->local, sdata, &sta->sta, tids);
-       mutex_unlock(&sdata->local->sta_mtx);
 
-       return ret;
+       return drv_reset_tid_config(sdata->local, sdata, &sta->sta, tids);
 }
 
 static int ieee80211_set_sar_specs(struct wiphy *wiphy,
@@ -4689,6 +4652,8 @@ static void
 ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
                                         u8 color, int enable, u64 changed)
 {
+       lockdep_assert_wiphy(sdata->local->hw.wiphy);
+
        sdata->vif.bss_conf.he_bss_color.color = color;
        sdata->vif.bss_conf.he_bss_color.enabled = enable;
        changed |= BSS_CHANGED_HE_BSS_COLOR;
@@ -4698,7 +4663,6 @@ ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
        if (!sdata->vif.bss_conf.nontransmitted && sdata->vif.mbssid_tx_vif) {
                struct ieee80211_sub_if_data *child;
 
-               mutex_lock(&sdata->local->iflist_mtx);
                list_for_each_entry(child, &sdata->local->interfaces, list) {
                        if (child != sdata && child->vif.mbssid_tx_vif == &sdata->vif) {
                                child->vif.bss_conf.he_bss_color.color = color;
@@ -4708,7 +4672,6 @@ ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
                                                                  BSS_CHANGED_HE_BSS_COLOR);
                        }
                }
-               mutex_unlock(&sdata->local->iflist_mtx);
        }
 }
 
@@ -4718,8 +4681,7 @@ static int ieee80211_color_change_finalize(struct ieee80211_sub_if_data *sdata)
        u64 changed = 0;
        int err;
 
-       sdata_assert_lock(sdata);
-       lockdep_assert_held(&local->mtx);
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        sdata->vif.bss_conf.color_change_active = false;
 
@@ -4737,28 +4699,24 @@ static int ieee80211_color_change_finalize(struct ieee80211_sub_if_data *sdata)
        return 0;
 }
 
-void ieee80211_color_change_finalize_work(struct work_struct *work)
+void ieee80211_color_change_finalize_work(struct wiphy *wiphy,
+                                         struct wiphy_work *work)
 {
        struct ieee80211_sub_if_data *sdata =
                container_of(work, struct ieee80211_sub_if_data,
                             deflink.color_change_finalize_work);
        struct ieee80211_local *local = sdata->local;
 
-       sdata_lock(sdata);
-       mutex_lock(&local->mtx);
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        /* AP might have been stopped while waiting for the lock. */
        if (!sdata->vif.bss_conf.color_change_active)
-               goto unlock;
+               return;
 
        if (!ieee80211_sdata_running(sdata))
-               goto unlock;
+               return;
 
        ieee80211_color_change_finalize(sdata);
-
-unlock:
-       mutex_unlock(&local->mtx);
-       sdata_unlock(sdata);
 }
 
 void ieee80211_color_collision_detection_work(struct work_struct *work)
@@ -4769,17 +4727,15 @@ void ieee80211_color_collision_detection_work(struct work_struct *work)
                             color_collision_detect_work);
        struct ieee80211_sub_if_data *sdata = link->sdata;
 
-       sdata_lock(sdata);
        cfg80211_obss_color_collision_notify(sdata->dev, link->color_bitmap);
-       sdata_unlock(sdata);
 }
 
 void ieee80211_color_change_finish(struct ieee80211_vif *vif)
 {
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
 
-       ieee80211_queue_work(&sdata->local->hw,
-                            &sdata->deflink.color_change_finalize_work);
+       wiphy_work_queue(sdata->local->hw.wiphy,
+                        &sdata->deflink.color_change_finalize_work);
 }
 EXPORT_SYMBOL_GPL(ieee80211_color_change_finish);
 
@@ -4815,13 +4771,11 @@ ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev,
        u64 changed = 0;
        int err;
 
-       sdata_assert_lock(sdata);
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        if (sdata->vif.bss_conf.nontransmitted)
                return -EINVAL;
 
-       mutex_lock(&local->mtx);
-
        /* don't allow another color change if one is already active or if csa
         * is active
         */
@@ -4846,7 +4800,6 @@ ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev,
                ieee80211_color_change_finalize(sdata);
 
 out:
-       mutex_unlock(&local->mtx);
 
        return err;
 }
@@ -4868,16 +4821,13 @@ static int ieee80211_add_intf_link(struct wiphy *wiphy,
                                   unsigned int link_id)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
-       int res;
+
+       lockdep_assert_wiphy(sdata->local->hw.wiphy);
 
        if (wdev->use_4addr)
                return -EOPNOTSUPP;
 
-       mutex_lock(&sdata->local->mtx);
-       res = ieee80211_vif_set_links(sdata, wdev->valid_links, 0);
-       mutex_unlock(&sdata->local->mtx);
-
-       return res;
+       return ieee80211_vif_set_links(sdata, wdev->valid_links, 0);
 }
 
 static void ieee80211_del_intf_link(struct wiphy *wiphy,
@@ -4886,9 +4836,9 @@ static void ieee80211_del_intf_link(struct wiphy *wiphy,
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
 
-       mutex_lock(&sdata->local->mtx);
+       lockdep_assert_wiphy(sdata->local->hw.wiphy);
+
        ieee80211_vif_set_links(sdata, wdev->valid_links, 0);
-       mutex_unlock(&sdata->local->mtx);
 }
 
 static int sta_add_link_station(struct ieee80211_local *local,
@@ -4928,13 +4878,10 @@ ieee80211_add_link_station(struct wiphy *wiphy, struct net_device *dev,
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = wiphy_priv(wiphy);
-       int ret;
 
-       mutex_lock(&sdata->local->sta_mtx);
-       ret = sta_add_link_station(local, sdata, params);
-       mutex_unlock(&sdata->local->sta_mtx);
+       lockdep_assert_wiphy(sdata->local->hw.wiphy);
 
-       return ret;
+       return sta_add_link_station(local, sdata, params);
 }
 
 static int sta_mod_link_station(struct ieee80211_local *local,
@@ -4959,13 +4906,10 @@ ieee80211_mod_link_station(struct wiphy *wiphy, struct net_device *dev,
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = wiphy_priv(wiphy);
-       int ret;
 
-       mutex_lock(&sdata->local->sta_mtx);
-       ret = sta_mod_link_station(local, sdata, params);
-       mutex_unlock(&sdata->local->sta_mtx);
+       lockdep_assert_wiphy(sdata->local->hw.wiphy);
 
-       return ret;
+       return sta_mod_link_station(local, sdata, params);
 }
 
 static int sta_del_link_station(struct ieee80211_sub_if_data *sdata,
@@ -4994,13 +4938,10 @@ ieee80211_del_link_station(struct wiphy *wiphy, struct net_device *dev,
                           struct link_station_del_parameters *params)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       int ret;
 
-       mutex_lock(&sdata->local->sta_mtx);
-       ret = sta_del_link_station(sdata, params);
-       mutex_unlock(&sdata->local->sta_mtx);
+       lockdep_assert_wiphy(sdata->local->hw.wiphy);
 
-       return ret;
+       return sta_del_link_station(sdata, params);
 }
 
 static int ieee80211_set_hw_timestamp(struct wiphy *wiphy,