Return-path: Received: from nick.hrz.tu-chemnitz.de ([134.109.228.11]:55271 "EHLO nick.hrz.tu-chemnitz.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935225Ab3DHMKH (ORCPT ); Mon, 8 Apr 2013 08:10:07 -0400 From: Simon Wunderlich To: linux-wireless@vger.kernel.org Cc: zefir.kurtisi@neratec.com, mathias.kretschmer@fokus.fraunhofer.de, Simon Wunderlich Subject: [PATCHv2] mac80211: fix recalc_radar hwconf sync problem Date: Mon, 8 Apr 2013 14:09:57 +0200 Message-Id: <1365422997-15728-1-git-send-email-siwu@hrz.tu-chemnitz.de> (sfid-20130408_141012_232911_870275CB) In-Reply-To: <1365165364.8515.24.camel@jlt4.sipsolutions.net> References: <1365165364.8515.24.camel@jlt4.sipsolutions.net> Sender: linux-wireless-owner@vger.kernel.org List-ID: local->hw.conf maybe not be synced when recalcing whether radar is enabled, sometimes leaving radar enabled even if it's not neccesary anymore. Fix this by: * setting radar_enabled when creating the chanctx * turning radar_enabled off before destroying the last channel context Reported-by: Zefir Kurtisi Signed-off-by: Simon Wunderlich --- net/mac80211/chan.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 931be41..1f54ffe 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -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); @@ -118,6 +137,7 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local, if (!local->use_chanctx) { local->_oper_channel_type = NL80211_CHAN_NO_HT; + local->hw.conf.radar_enabled = false; ieee80211_hw_config(local, 0); } else { drv_remove_chanctx(local, ctx); @@ -237,19 +257,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; -- 1.7.10.4