diff options
author | Luciano Coelho <luciano.coelho@intel.com> | 2014-01-30 22:08:16 +0200 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-04-09 10:55:50 +0200 |
commit | 33ffd952c252b7943dd5d051af3eeacc0bb3c23e (patch) | |
tree | 454d4a14501be70d702a85f31457023f2b28be2b /net | |
parent | 4e141dad266908735967b0961c8d90187825e0bc (diff) | |
download | linux-33ffd952c252b7943dd5d051af3eeacc0bb3c23e.tar.bz2 |
mac80211: split ieee80211_vif_change_channel in two
ieee80211_vif_change_channel() locks chanctx_mtx. When implementing
channel reservation for CS, we will need to call the function to
change channel when the lock is already held, so split the part that
requires the lock out and leave the locking in the original function.
Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/chan.c | 58 |
1 files changed, 33 insertions, 25 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index db0a344968eb..503ee3083409 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -570,39 +570,20 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, return ret; } -int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, - u32 *changed) +static int __ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, + struct ieee80211_chanctx *ctx, + u32 *changed) { struct ieee80211_local *local = sdata->local; - struct ieee80211_chanctx_conf *conf; - struct ieee80211_chanctx *ctx; const struct cfg80211_chan_def *chandef = &sdata->csa_chandef; - int ret; u32 chanctx_changed = 0; - lockdep_assert_held(&local->mtx); - - /* should never be called if not performing a channel switch. */ - if (WARN_ON(!sdata->vif.csa_active)) - return -EINVAL; - if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, IEEE80211_CHAN_DISABLED)) return -EINVAL; - mutex_lock(&local->chanctx_mtx); - conf = rcu_dereference_protected(sdata->vif.chanctx_conf, - lockdep_is_held(&local->chanctx_mtx)); - if (!conf) { - ret = -EINVAL; - goto out; - } - - ctx = container_of(conf, struct ieee80211_chanctx, conf); - if (ctx->refcount != 1) { - ret = -EINVAL; - goto out; - } + if (ctx->refcount != 1) + return -EINVAL; if (sdata->vif.bss_conf.chandef.width != chandef->width) { chanctx_changed = IEEE80211_CHANCTX_CHANGE_WIDTH; @@ -620,7 +601,34 @@ int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, ieee80211_recalc_radar_chanctx(local, ctx); ieee80211_recalc_chanctx_min_def(local, ctx); - ret = 0; + return 0; +} + +int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, + u32 *changed) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_chanctx_conf *conf; + struct ieee80211_chanctx *ctx; + int ret; + + lockdep_assert_held(&local->mtx); + + /* should never be called if not performing a channel switch. */ + if (WARN_ON(!sdata->vif.csa_active)) + return -EINVAL; + + mutex_lock(&local->chanctx_mtx); + conf = rcu_dereference_protected(sdata->vif.chanctx_conf, + lockdep_is_held(&local->chanctx_mtx)); + if (!conf) { + ret = -EINVAL; + goto out; + } + + ctx = container_of(conf, struct ieee80211_chanctx, conf); + + ret = __ieee80211_vif_change_channel(sdata, ctx, changed); out: mutex_unlock(&local->chanctx_mtx); return ret; |