diff options
Diffstat (limited to 'net/mac80211/chan.c')
-rw-r--r-- | net/mac80211/chan.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 166165efd8e2..03e8d2e3270e 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -79,6 +79,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
79 | enum ieee80211_chanctx_mode mode) | 79 | enum ieee80211_chanctx_mode mode) |
80 | { | 80 | { |
81 | struct ieee80211_chanctx *ctx; | 81 | struct ieee80211_chanctx *ctx; |
82 | u32 changed; | ||
82 | int err; | 83 | int err; |
83 | 84 | ||
84 | lockdep_assert_held(&local->chanctx_mtx); | 85 | lockdep_assert_held(&local->chanctx_mtx); |
@@ -95,6 +96,13 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
95 | if (!local->use_chanctx) | 96 | if (!local->use_chanctx) |
96 | local->hw.conf.radar_enabled = ctx->conf.radar_enabled; | 97 | local->hw.conf.radar_enabled = ctx->conf.radar_enabled; |
97 | 98 | ||
99 | /* acquire mutex to prevent idle from changing */ | ||
100 | mutex_lock(&local->mtx); | ||
101 | /* turn idle off *before* setting channel -- some drivers need that */ | ||
102 | changed = ieee80211_idle_off(local); | ||
103 | if (changed) | ||
104 | ieee80211_hw_config(local, changed); | ||
105 | |||
98 | if (!local->use_chanctx) { | 106 | if (!local->use_chanctx) { |
99 | local->_oper_chandef = *chandef; | 107 | local->_oper_chandef = *chandef; |
100 | ieee80211_hw_config(local, 0); | 108 | ieee80211_hw_config(local, 0); |
@@ -102,14 +110,17 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
102 | err = drv_add_chanctx(local, ctx); | 110 | err = drv_add_chanctx(local, ctx); |
103 | if (err) { | 111 | if (err) { |
104 | kfree(ctx); | 112 | kfree(ctx); |
105 | return ERR_PTR(err); | 113 | ctx = ERR_PTR(err); |
114 | |||
115 | ieee80211_recalc_idle(local); | ||
116 | goto out; | ||
106 | } | 117 | } |
107 | } | 118 | } |
108 | 119 | ||
120 | /* and keep the mutex held until the new chanctx is on the list */ | ||
109 | list_add_rcu(&ctx->list, &local->chanctx_list); | 121 | list_add_rcu(&ctx->list, &local->chanctx_list); |
110 | 122 | ||
111 | mutex_lock(&local->mtx); | 123 | out: |
112 | ieee80211_recalc_idle(local); | ||
113 | mutex_unlock(&local->mtx); | 124 | mutex_unlock(&local->mtx); |
114 | 125 | ||
115 | return ctx; | 126 | return ctx; |