aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c26
-rw-r--r--net/mac80211/chan.c21
-rw-r--r--net/mac80211/ibss.c7
-rw-r--r--net/mac80211/iface.c6
-rw-r--r--net/mac80211/mlme.c25
-rw-r--r--net/mac80211/util.c8
6 files changed, 73 insertions, 20 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index bfe54daab4b1..aab3c2f29de3 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -828,6 +828,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
828 if (cfg80211_chandef_identical(&local->monitor_chandef, chandef)) 828 if (cfg80211_chandef_identical(&local->monitor_chandef, chandef))
829 return 0; 829 return 0;
830 830
831 mutex_lock(&local->mtx);
831 mutex_lock(&local->iflist_mtx); 832 mutex_lock(&local->iflist_mtx);
832 if (local->use_chanctx) { 833 if (local->use_chanctx) {
833 sdata = rcu_dereference_protected( 834 sdata = rcu_dereference_protected(
@@ -846,6 +847,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
846 if (ret == 0) 847 if (ret == 0)
847 local->monitor_chandef = *chandef; 848 local->monitor_chandef = *chandef;
848 mutex_unlock(&local->iflist_mtx); 849 mutex_unlock(&local->iflist_mtx);
850 mutex_unlock(&local->mtx);
849 851
850 return ret; 852 return ret;
851} 853}
@@ -951,6 +953,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
951 struct cfg80211_ap_settings *params) 953 struct cfg80211_ap_settings *params)
952{ 954{
953 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 955 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
956 struct ieee80211_local *local = sdata->local;
954 struct beacon_data *old; 957 struct beacon_data *old;
955 struct ieee80211_sub_if_data *vlan; 958 struct ieee80211_sub_if_data *vlan;
956 u32 changed = BSS_CHANGED_BEACON_INT | 959 u32 changed = BSS_CHANGED_BEACON_INT |
@@ -969,8 +972,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
969 sdata->needed_rx_chains = sdata->local->rx_chains; 972 sdata->needed_rx_chains = sdata->local->rx_chains;
970 sdata->radar_required = params->radar_required; 973 sdata->radar_required = params->radar_required;
971 974
975 mutex_lock(&local->mtx);
972 err = ieee80211_vif_use_channel(sdata, &params->chandef, 976 err = ieee80211_vif_use_channel(sdata, &params->chandef,
973 IEEE80211_CHANCTX_SHARED); 977 IEEE80211_CHANCTX_SHARED);
978 mutex_unlock(&local->mtx);
974 if (err) 979 if (err)
975 return err; 980 return err;
976 ieee80211_vif_copy_chanctx_to_vlans(sdata, false); 981 ieee80211_vif_copy_chanctx_to_vlans(sdata, false);
@@ -1121,7 +1126,9 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1121 skb_queue_purge(&sdata->u.ap.ps.bc_buf); 1126 skb_queue_purge(&sdata->u.ap.ps.bc_buf);
1122 1127
1123 ieee80211_vif_copy_chanctx_to_vlans(sdata, true); 1128 ieee80211_vif_copy_chanctx_to_vlans(sdata, true);
1129 mutex_lock(&local->mtx);
1124 ieee80211_vif_release_channel(sdata); 1130 ieee80211_vif_release_channel(sdata);
1131 mutex_unlock(&local->mtx);
1125 1132
1126 return 0; 1133 return 0;
1127} 1134}
@@ -1944,8 +1951,10 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
1944 sdata->smps_mode = IEEE80211_SMPS_OFF; 1951 sdata->smps_mode = IEEE80211_SMPS_OFF;
1945 sdata->needed_rx_chains = sdata->local->rx_chains; 1952 sdata->needed_rx_chains = sdata->local->rx_chains;
1946 1953
1954 mutex_lock(&sdata->local->mtx);
1947 err = ieee80211_vif_use_channel(sdata, &setup->chandef, 1955 err = ieee80211_vif_use_channel(sdata, &setup->chandef,
1948 IEEE80211_CHANCTX_SHARED); 1956 IEEE80211_CHANCTX_SHARED);
1957 mutex_unlock(&sdata->local->mtx);
1949 if (err) 1958 if (err)
1950 return err; 1959 return err;
1951 1960
@@ -1957,7 +1966,9 @@ static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
1957 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1966 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1958 1967
1959 ieee80211_stop_mesh(sdata); 1968 ieee80211_stop_mesh(sdata);
1969 mutex_lock(&sdata->local->mtx);
1960 ieee80211_vif_release_channel(sdata); 1970 ieee80211_vif_release_channel(sdata);
1971 mutex_unlock(&sdata->local->mtx);
1961 1972
1962 return 0; 1973 return 0;
1963} 1974}
@@ -2895,8 +2906,11 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
2895 unsigned long timeout; 2906 unsigned long timeout;
2896 int err; 2907 int err;
2897 2908
2898 if (!list_empty(&local->roc_list) || local->scanning) 2909 mutex_lock(&local->mtx);
2899 return -EBUSY; 2910 if (!list_empty(&local->roc_list) || local->scanning) {
2911 err = -EBUSY;
2912 goto out_unlock;
2913 }
2900 2914
2901 /* whatever, but channel contexts should not complain about that one */ 2915 /* whatever, but channel contexts should not complain about that one */
2902 sdata->smps_mode = IEEE80211_SMPS_OFF; 2916 sdata->smps_mode = IEEE80211_SMPS_OFF;
@@ -2906,13 +2920,15 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
2906 err = ieee80211_vif_use_channel(sdata, chandef, 2920 err = ieee80211_vif_use_channel(sdata, chandef,
2907 IEEE80211_CHANCTX_SHARED); 2921 IEEE80211_CHANCTX_SHARED);
2908 if (err) 2922 if (err)
2909 return err; 2923 goto out_unlock;
2910 2924
2911 timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); 2925 timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
2912 ieee80211_queue_delayed_work(&sdata->local->hw, 2926 ieee80211_queue_delayed_work(&sdata->local->hw,
2913 &sdata->dfs_cac_timer_work, timeout); 2927 &sdata->dfs_cac_timer_work, timeout);
2914 2928
2915 return 0; 2929 out_unlock:
2930 mutex_unlock(&local->mtx);
2931 return err;
2916} 2932}
2917 2933
2918static struct cfg80211_beacon_data * 2934static struct cfg80211_beacon_data *
@@ -2988,7 +3004,9 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
2988 goto unlock; 3004 goto unlock;
2989 3005
2990 sdata->radar_required = sdata->csa_radar_required; 3006 sdata->radar_required = sdata->csa_radar_required;
3007 mutex_lock(&local->mtx);
2991 err = ieee80211_vif_change_channel(sdata, &changed); 3008 err = ieee80211_vif_change_channel(sdata, &changed);
3009 mutex_unlock(&local->mtx);
2992 if (WARN_ON(err < 0)) 3010 if (WARN_ON(err < 0))
2993 goto unlock; 3011 goto unlock;
2994 3012
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index f20a98a70cc0..f43613a97dd6 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -232,8 +232,8 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
232 if (!local->use_chanctx) 232 if (!local->use_chanctx)
233 local->hw.conf.radar_enabled = ctx->conf.radar_enabled; 233 local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
234 234
235 /* acquire mutex to prevent idle from changing */ 235 /* we hold the mutex to prevent idle from changing */
236 mutex_lock(&local->mtx); 236 lockdep_assert_held(&local->mtx);
237 /* turn idle off *before* setting channel -- some drivers need that */ 237 /* turn idle off *before* setting channel -- some drivers need that */
238 changed = ieee80211_idle_off(local); 238 changed = ieee80211_idle_off(local);
239 if (changed) 239 if (changed)
@@ -246,19 +246,14 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
246 err = drv_add_chanctx(local, ctx); 246 err = drv_add_chanctx(local, ctx);
247 if (err) { 247 if (err) {
248 kfree(ctx); 248 kfree(ctx);
249 ctx = ERR_PTR(err);
250
251 ieee80211_recalc_idle(local); 249 ieee80211_recalc_idle(local);
252 goto out; 250 return ERR_PTR(err);
253 } 251 }
254 } 252 }
255 253
256 /* and keep the mutex held until the new chanctx is on the list */ 254 /* and keep the mutex held until the new chanctx is on the list */
257 list_add_rcu(&ctx->list, &local->chanctx_list); 255 list_add_rcu(&ctx->list, &local->chanctx_list);
258 256
259 out:
260 mutex_unlock(&local->mtx);
261
262 return ctx; 257 return ctx;
263} 258}
264 259
@@ -294,9 +289,7 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
294 /* throw a warning if this wasn't the only channel context. */ 289 /* throw a warning if this wasn't the only channel context. */
295 WARN_ON(check_single_channel && !list_empty(&local->chanctx_list)); 290 WARN_ON(check_single_channel && !list_empty(&local->chanctx_list));
296 291
297 mutex_lock(&local->mtx);
298 ieee80211_recalc_idle(local); 292 ieee80211_recalc_idle(local);
299 mutex_unlock(&local->mtx);
300} 293}
301 294
302static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, 295static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
@@ -364,6 +357,8 @@ static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
364 bool radar_enabled; 357 bool radar_enabled;
365 358
366 lockdep_assert_held(&local->chanctx_mtx); 359 lockdep_assert_held(&local->chanctx_mtx);
360 /* for setting local->radar_detect_enabled */
361 lockdep_assert_held(&local->mtx);
367 362
368 radar_enabled = ieee80211_is_radar_required(local); 363 radar_enabled = ieee80211_is_radar_required(local);
369 364
@@ -518,6 +513,8 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
518 struct ieee80211_chanctx *ctx; 513 struct ieee80211_chanctx *ctx;
519 int ret; 514 int ret;
520 515
516 lockdep_assert_held(&local->mtx);
517
521 WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev)); 518 WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
522 519
523 mutex_lock(&local->chanctx_mtx); 520 mutex_lock(&local->chanctx_mtx);
@@ -558,6 +555,8 @@ int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
558 int ret; 555 int ret;
559 u32 chanctx_changed = 0; 556 u32 chanctx_changed = 0;
560 557
558 lockdep_assert_held(&local->mtx);
559
561 /* should never be called if not performing a channel switch. */ 560 /* should never be called if not performing a channel switch. */
562 if (WARN_ON(!sdata->vif.csa_active)) 561 if (WARN_ON(!sdata->vif.csa_active))
563 return -EINVAL; 562 return -EINVAL;
@@ -655,6 +654,8 @@ void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
655{ 654{
656 WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev)); 655 WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
657 656
657 lockdep_assert_held(&sdata->local->mtx);
658
658 mutex_lock(&sdata->local->chanctx_mtx); 659 mutex_lock(&sdata->local->chanctx_mtx);
659 __ieee80211_vif_release_channel(sdata); 660 __ieee80211_vif_release_channel(sdata);
660 mutex_unlock(&sdata->local->chanctx_mtx); 661 mutex_unlock(&sdata->local->chanctx_mtx);
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index d6ba841437b6..771080ec7212 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -293,14 +293,17 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
293 radar_required = true; 293 radar_required = true;
294 } 294 }
295 295
296 mutex_lock(&local->mtx);
296 ieee80211_vif_release_channel(sdata); 297 ieee80211_vif_release_channel(sdata);
297 if (ieee80211_vif_use_channel(sdata, &chandef, 298 if (ieee80211_vif_use_channel(sdata, &chandef,
298 ifibss->fixed_channel ? 299 ifibss->fixed_channel ?
299 IEEE80211_CHANCTX_SHARED : 300 IEEE80211_CHANCTX_SHARED :
300 IEEE80211_CHANCTX_EXCLUSIVE)) { 301 IEEE80211_CHANCTX_EXCLUSIVE)) {
301 sdata_info(sdata, "Failed to join IBSS, no channel context\n"); 302 sdata_info(sdata, "Failed to join IBSS, no channel context\n");
303 mutex_unlock(&local->mtx);
302 return; 304 return;
303 } 305 }
306 mutex_unlock(&local->mtx);
304 307
305 memcpy(ifibss->bssid, bssid, ETH_ALEN); 308 memcpy(ifibss->bssid, bssid, ETH_ALEN);
306 309
@@ -363,7 +366,9 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
363 sdata->vif.bss_conf.ssid_len = 0; 366 sdata->vif.bss_conf.ssid_len = 0;
364 RCU_INIT_POINTER(ifibss->presp, NULL); 367 RCU_INIT_POINTER(ifibss->presp, NULL);
365 kfree_rcu(presp, rcu_head); 368 kfree_rcu(presp, rcu_head);
369 mutex_lock(&local->mtx);
366 ieee80211_vif_release_channel(sdata); 370 ieee80211_vif_release_channel(sdata);
371 mutex_unlock(&local->mtx);
367 sdata_info(sdata, "Failed to join IBSS, driver failure: %d\n", 372 sdata_info(sdata, "Failed to join IBSS, driver failure: %d\n",
368 err); 373 err);
369 return; 374 return;
@@ -747,7 +752,9 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata)
747 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | 752 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
748 BSS_CHANGED_IBSS); 753 BSS_CHANGED_IBSS);
749 drv_leave_ibss(local, sdata); 754 drv_leave_ibss(local, sdata);
755 mutex_lock(&local->mtx);
750 ieee80211_vif_release_channel(sdata); 756 ieee80211_vif_release_channel(sdata);
757 mutex_unlock(&local->mtx);
751} 758}
752 759
753static void ieee80211_csa_connection_drop_work(struct work_struct *work) 760static void ieee80211_csa_connection_drop_work(struct work_struct *work)
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 0c0be9097664..0aa9675319ef 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -418,8 +418,10 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
418 return ret; 418 return ret;
419 } 419 }
420 420
421 mutex_lock(&local->mtx);
421 ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, 422 ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
422 IEEE80211_CHANCTX_EXCLUSIVE); 423 IEEE80211_CHANCTX_EXCLUSIVE);
424 mutex_unlock(&local->mtx);
423 if (ret) { 425 if (ret) {
424 drv_remove_interface(local, sdata); 426 drv_remove_interface(local, sdata);
425 kfree(sdata); 427 kfree(sdata);
@@ -456,7 +458,9 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
456 458
457 synchronize_net(); 459 synchronize_net();
458 460
461 mutex_lock(&local->mtx);
459 ieee80211_vif_release_channel(sdata); 462 ieee80211_vif_release_channel(sdata);
463 mutex_unlock(&local->mtx);
460 464
461 drv_remove_interface(local, sdata); 465 drv_remove_interface(local, sdata);
462 466
@@ -826,7 +830,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
826 if (sdata->wdev.cac_started) { 830 if (sdata->wdev.cac_started) {
827 chandef = sdata->vif.bss_conf.chandef; 831 chandef = sdata->vif.bss_conf.chandef;
828 WARN_ON(local->suspended); 832 WARN_ON(local->suspended);
833 mutex_lock(&local->mtx);
829 ieee80211_vif_release_channel(sdata); 834 ieee80211_vif_release_channel(sdata);
835 mutex_unlock(&local->mtx);
830 cfg80211_cac_event(sdata->dev, &chandef, 836 cfg80211_cac_event(sdata->dev, &chandef,
831 NL80211_RADAR_CAC_ABORTED, 837 NL80211_RADAR_CAC_ABORTED,
832 GFP_KERNEL); 838 GFP_KERNEL);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 9c2c7ee2cc30..fc1d82465b3c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -888,7 +888,9 @@ static void ieee80211_chswitch_work(struct work_struct *work)
888 if (!ifmgd->associated) 888 if (!ifmgd->associated)
889 goto out; 889 goto out;
890 890
891 mutex_lock(&local->mtx);
891 ret = ieee80211_vif_change_channel(sdata, &changed); 892 ret = ieee80211_vif_change_channel(sdata, &changed);
893 mutex_unlock(&local->mtx);
892 if (ret) { 894 if (ret) {
893 sdata_info(sdata, 895 sdata_info(sdata,
894 "vif channel switch failed, disconnecting\n"); 896 "vif channel switch failed, disconnecting\n");
@@ -1401,10 +1403,14 @@ void ieee80211_dfs_cac_timer_work(struct work_struct *work)
1401 dfs_cac_timer_work); 1403 dfs_cac_timer_work);
1402 struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chandef; 1404 struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chandef;
1403 1405
1404 ieee80211_vif_release_channel(sdata); 1406 mutex_lock(&sdata->local->mtx);
1405 cfg80211_cac_event(sdata->dev, &chandef, 1407 if (sdata->wdev.cac_started) {
1406 NL80211_RADAR_CAC_FINISHED, 1408 ieee80211_vif_release_channel(sdata);
1407 GFP_KERNEL); 1409 cfg80211_cac_event(sdata->dev, &chandef,
1410 NL80211_RADAR_CAC_FINISHED,
1411 GFP_KERNEL);
1412 }
1413 mutex_unlock(&sdata->local->mtx);
1408} 1414}
1409 1415
1410/* MLME */ 1416/* MLME */
@@ -1747,7 +1753,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1747 ifmgd->have_beacon = false; 1753 ifmgd->have_beacon = false;
1748 1754
1749 ifmgd->flags = 0; 1755 ifmgd->flags = 0;
1756 mutex_lock(&local->mtx);
1750 ieee80211_vif_release_channel(sdata); 1757 ieee80211_vif_release_channel(sdata);
1758 mutex_unlock(&local->mtx);
1751 1759
1752 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; 1760 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
1753} 1761}
@@ -2070,7 +2078,9 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
2070 memset(sdata->u.mgd.bssid, 0, ETH_ALEN); 2078 memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
2071 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); 2079 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2072 sdata->u.mgd.flags = 0; 2080 sdata->u.mgd.flags = 0;
2081 mutex_lock(&sdata->local->mtx);
2073 ieee80211_vif_release_channel(sdata); 2082 ieee80211_vif_release_channel(sdata);
2083 mutex_unlock(&sdata->local->mtx);
2074 } 2084 }
2075 2085
2076 cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss); 2086 cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss);
@@ -2319,7 +2329,9 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
2319 memset(sdata->u.mgd.bssid, 0, ETH_ALEN); 2329 memset(sdata->u.mgd.bssid, 0, ETH_ALEN);
2320 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); 2330 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2321 sdata->u.mgd.flags = 0; 2331 sdata->u.mgd.flags = 0;
2332 mutex_lock(&sdata->local->mtx);
2322 ieee80211_vif_release_channel(sdata); 2333 ieee80211_vif_release_channel(sdata);
2334 mutex_unlock(&sdata->local->mtx);
2323 } 2335 }
2324 2336
2325 kfree(assoc_data); 2337 kfree(assoc_data);
@@ -3670,6 +3682,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3670 /* will change later if needed */ 3682 /* will change later if needed */
3671 sdata->smps_mode = IEEE80211_SMPS_OFF; 3683 sdata->smps_mode = IEEE80211_SMPS_OFF;
3672 3684
3685 mutex_lock(&local->mtx);
3673 /* 3686 /*
3674 * If this fails (possibly due to channel context sharing 3687 * If this fails (possibly due to channel context sharing
3675 * on incompatible channels, e.g. 80+80 and 160 sharing the 3688 * on incompatible channels, e.g. 80+80 and 160 sharing the
@@ -3681,13 +3694,15 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3681 /* don't downgrade for 5 and 10 MHz channels, though. */ 3694 /* don't downgrade for 5 and 10 MHz channels, though. */
3682 if (chandef.width == NL80211_CHAN_WIDTH_5 || 3695 if (chandef.width == NL80211_CHAN_WIDTH_5 ||
3683 chandef.width == NL80211_CHAN_WIDTH_10) 3696 chandef.width == NL80211_CHAN_WIDTH_10)
3684 return ret; 3697 goto out;
3685 3698
3686 while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { 3699 while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
3687 ifmgd->flags |= ieee80211_chandef_downgrade(&chandef); 3700 ifmgd->flags |= ieee80211_chandef_downgrade(&chandef);
3688 ret = ieee80211_vif_use_channel(sdata, &chandef, 3701 ret = ieee80211_vif_use_channel(sdata, &chandef,
3689 IEEE80211_CHANCTX_SHARED); 3702 IEEE80211_CHANCTX_SHARED);
3690 } 3703 }
3704 out:
3705 mutex_unlock(&local->mtx);
3691 return ret; 3706 return ret;
3692} 3707}
3693 3708
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 656648b9b9d3..ed93504d24b8 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2315,9 +2315,14 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
2315 struct ieee80211_sub_if_data *sdata; 2315 struct ieee80211_sub_if_data *sdata;
2316 struct cfg80211_chan_def chandef; 2316 struct cfg80211_chan_def chandef;
2317 2317
2318 mutex_lock(&local->mtx);
2318 mutex_lock(&local->iflist_mtx); 2319 mutex_lock(&local->iflist_mtx);
2319 list_for_each_entry(sdata, &local->interfaces, list) { 2320 list_for_each_entry(sdata, &local->interfaces, list) {
2320 cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); 2321 /* it might be waiting for the local->mtx, but then
2322 * by the time it gets it, sdata->wdev.cac_started
2323 * will no longer be true
2324 */
2325 cancel_delayed_work(&sdata->dfs_cac_timer_work);
2321 2326
2322 if (sdata->wdev.cac_started) { 2327 if (sdata->wdev.cac_started) {
2323 chandef = sdata->vif.bss_conf.chandef; 2328 chandef = sdata->vif.bss_conf.chandef;
@@ -2329,6 +2334,7 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
2329 } 2334 }
2330 } 2335 }
2331 mutex_unlock(&local->iflist_mtx); 2336 mutex_unlock(&local->iflist_mtx);
2337 mutex_unlock(&local->mtx);
2332} 2338}
2333 2339
2334void ieee80211_dfs_radar_detected_work(struct work_struct *work) 2340void ieee80211_dfs_radar_detected_work(struct work_struct *work)