|
@@ -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,
|
|
@@ -75,6 +91,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;
|
|
|
|
|
|
if (!local->use_chanctx) {
|
|
|
local->_oper_chandef = *chandef;
|
|
@@ -99,6 +118,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);
|
|
@@ -108,6 +128,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);
|
|
@@ -116,6 +144,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);
|
|
@@ -227,19 +258,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;
|