]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/mac80211/chan.c
Merge remote-tracking branch 'wireless-next/master' into mac80211-next
[karo-tx-linux.git] / net / mac80211 / chan.c
index 7d0baa89c784888926b98d2a84fc329f04c75122..03e8d2e3270e23f0e97a58595513b33fcb048cb3 100644 (file)
@@ -57,6 +57,22 @@ ieee80211_find_chanctx(struct ieee80211_local *local,
        return NULL;
 }
 
+static bool ieee80211_is_radar_required(struct ieee80211_local *local)
+{
+       struct ieee80211_sub_if_data *sdata;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+               if (sdata->radar_required) {
+                       rcu_read_unlock();
+                       return true;
+               }
+       }
+       rcu_read_unlock();
+
+       return false;
+}
+
 static struct ieee80211_chanctx *
 ieee80211_new_chanctx(struct ieee80211_local *local,
                      const struct cfg80211_chan_def *chandef,
@@ -76,6 +92,9 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
        ctx->conf.rx_chains_static = 1;
        ctx->conf.rx_chains_dynamic = 1;
        ctx->mode = mode;
+       ctx->conf.radar_enabled = ieee80211_is_radar_required(local);
+       if (!local->use_chanctx)
+               local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
 
        /* acquire mutex to prevent idle from changing */
        mutex_lock(&local->mtx);
@@ -110,6 +129,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
 static void ieee80211_free_chanctx(struct ieee80211_local *local,
                                   struct ieee80211_chanctx *ctx)
 {
+       bool check_single_channel = false;
        lockdep_assert_held(&local->chanctx_mtx);
 
        WARN_ON_ONCE(ctx->refcount != 0);
@@ -119,6 +139,14 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
                chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
                chandef->center_freq1 = chandef->chan->center_freq;
                chandef->center_freq2 = 0;
+
+               /* NOTE: Disabling radar is only valid here for
+                * single channel context. To be sure, check it ...
+                */
+               if (local->hw.conf.radar_enabled)
+                       check_single_channel = true;
+               local->hw.conf.radar_enabled = false;
+
                ieee80211_hw_config(local, 0);
        } else {
                drv_remove_chanctx(local, ctx);
@@ -127,6 +155,9 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
        list_del_rcu(&ctx->list);
        kfree_rcu(ctx, rcu_head);
 
+       /* throw a warning if this wasn't the only channel context. */
+       WARN_ON(check_single_channel && !list_empty(&local->chanctx_list));
+
        mutex_lock(&local->mtx);
        ieee80211_recalc_idle(local);
        mutex_unlock(&local->mtx);
@@ -238,19 +269,11 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
 void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
                                    struct ieee80211_chanctx *chanctx)
 {
-       struct ieee80211_sub_if_data *sdata;
-       bool radar_enabled = false;
+       bool radar_enabled;
 
        lockdep_assert_held(&local->chanctx_mtx);
 
-       rcu_read_lock();
-       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-               if (sdata->radar_required) {
-                       radar_enabled = true;
-                       break;
-               }
-       }
-       rcu_read_unlock();
+       radar_enabled = ieee80211_is_radar_required(local);
 
        if (radar_enabled == chanctx->conf.radar_enabled)
                return;