aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-04-09 09:29:28 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-04-25 11:08:30 -0400
commit0288157b2ad085e564fb563fbe7794c9ffae4169 (patch)
treec8f8c9646b67aab923271c7cc9322439de3e1ef0
parente3afb920227d37fe72914350c41621c028539077 (diff)
mac80211: improve find_chanctx() for reservations
This allows new vifs to be assigned to a chanctx as long as chanctx's reservation chandefs (if any) and chanctx's current chandef (implied by assigned vifs at the time, if any) and the new vif chandef are all compatible. This implies it is impossible to assign a new vif to an in-place reservation chanctx. This gives no advantages for single-channel hardware. It makes sense for multi-channel hardware only. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/chan.c56
1 files changed, 29 insertions, 27 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 79eac96d9e5f..0dfb04a07f30 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -28,6 +28,29 @@ static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local)
28 return ieee80211_num_chanctx(local) < ieee80211_max_num_channels(local); 28 return ieee80211_num_chanctx(local) < ieee80211_max_num_channels(local);
29} 29}
30 30
31static const struct cfg80211_chan_def *
32ieee80211_chanctx_reserved_chandef(struct ieee80211_local *local,
33 struct ieee80211_chanctx *ctx,
34 const struct cfg80211_chan_def *compat)
35{
36 struct ieee80211_sub_if_data *sdata;
37
38 lockdep_assert_held(&local->chanctx_mtx);
39
40 list_for_each_entry(sdata, &ctx->reserved_vifs,
41 reserved_chanctx_list) {
42 if (!compat)
43 compat = &sdata->reserved_chandef;
44
45 compat = cfg80211_chandef_compatible(&sdata->reserved_chandef,
46 compat);
47 if (!compat)
48 break;
49 }
50
51 return compat;
52}
53
31static enum nl80211_chan_width ieee80211_get_sta_bw(struct ieee80211_sta *sta) 54static enum nl80211_chan_width ieee80211_get_sta_bw(struct ieee80211_sta *sta)
32{ 55{
33 switch (sta->bandwidth) { 56 switch (sta->bandwidth) {
@@ -187,27 +210,6 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local,
187 } 210 }
188} 211}
189 212
190static bool ieee80211_chanctx_is_reserved(struct ieee80211_local *local,
191 struct ieee80211_chanctx *ctx)
192{
193 struct ieee80211_sub_if_data *sdata;
194 bool ret = false;
195
196 lockdep_assert_held(&local->chanctx_mtx);
197 rcu_read_lock();
198 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
199 if (!ieee80211_sdata_running(sdata))
200 continue;
201 if (sdata->reserved_chanctx == ctx) {
202 ret = true;
203 break;
204 }
205 }
206
207 rcu_read_unlock();
208 return ret;
209}
210
211static struct ieee80211_chanctx * 213static struct ieee80211_chanctx *
212ieee80211_find_chanctx(struct ieee80211_local *local, 214ieee80211_find_chanctx(struct ieee80211_local *local,
213 const struct cfg80211_chan_def *chandef, 215 const struct cfg80211_chan_def *chandef,
@@ -223,18 +225,18 @@ ieee80211_find_chanctx(struct ieee80211_local *local,
223 list_for_each_entry(ctx, &local->chanctx_list, list) { 225 list_for_each_entry(ctx, &local->chanctx_list, list) {
224 const struct cfg80211_chan_def *compat; 226 const struct cfg80211_chan_def *compat;
225 227
226 /* We don't support chanctx reservation for multiple 228 if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
227 * vifs yet, so don't allow reserved chanctxs to be
228 * reused.
229 */
230 if ((ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) ||
231 ieee80211_chanctx_is_reserved(local, ctx))
232 continue; 229 continue;
233 230
234 compat = cfg80211_chandef_compatible(&ctx->conf.def, chandef); 231 compat = cfg80211_chandef_compatible(&ctx->conf.def, chandef);
235 if (!compat) 232 if (!compat)
236 continue; 233 continue;
237 234
235 compat = ieee80211_chanctx_reserved_chandef(local, ctx,
236 compat);
237 if (!compat)
238 continue;
239
238 ieee80211_change_chanctx(local, ctx, compat); 240 ieee80211_change_chanctx(local, ctx, compat);
239 241
240 return ctx; 242 return ctx;