xref: /openbmc/linux/net/mac80211/chan.c (revision c819e2cf)
1 /*
2  * mac80211 - channel management
3  */
4 
5 #include <linux/nl80211.h>
6 #include <linux/export.h>
7 #include <linux/rtnetlink.h>
8 #include <net/cfg80211.h>
9 #include "ieee80211_i.h"
10 #include "driver-ops.h"
11 
12 static int ieee80211_chanctx_num_assigned(struct ieee80211_local *local,
13 					  struct ieee80211_chanctx *ctx)
14 {
15 	struct ieee80211_sub_if_data *sdata;
16 	int num = 0;
17 
18 	lockdep_assert_held(&local->chanctx_mtx);
19 
20 	list_for_each_entry(sdata, &ctx->assigned_vifs, assigned_chanctx_list)
21 		num++;
22 
23 	return num;
24 }
25 
26 static int ieee80211_chanctx_num_reserved(struct ieee80211_local *local,
27 					  struct ieee80211_chanctx *ctx)
28 {
29 	struct ieee80211_sub_if_data *sdata;
30 	int num = 0;
31 
32 	lockdep_assert_held(&local->chanctx_mtx);
33 
34 	list_for_each_entry(sdata, &ctx->reserved_vifs, reserved_chanctx_list)
35 		num++;
36 
37 	return num;
38 }
39 
40 int ieee80211_chanctx_refcount(struct ieee80211_local *local,
41 			       struct ieee80211_chanctx *ctx)
42 {
43 	return ieee80211_chanctx_num_assigned(local, ctx) +
44 	       ieee80211_chanctx_num_reserved(local, ctx);
45 }
46 
47 static int ieee80211_num_chanctx(struct ieee80211_local *local)
48 {
49 	struct ieee80211_chanctx *ctx;
50 	int num = 0;
51 
52 	lockdep_assert_held(&local->chanctx_mtx);
53 
54 	list_for_each_entry(ctx, &local->chanctx_list, list)
55 		num++;
56 
57 	return num;
58 }
59 
60 static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local)
61 {
62 	lockdep_assert_held(&local->chanctx_mtx);
63 	return ieee80211_num_chanctx(local) < ieee80211_max_num_channels(local);
64 }
65 
66 static struct ieee80211_chanctx *
67 ieee80211_vif_get_chanctx(struct ieee80211_sub_if_data *sdata)
68 {
69 	struct ieee80211_local *local __maybe_unused = sdata->local;
70 	struct ieee80211_chanctx_conf *conf;
71 
72 	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
73 					 lockdep_is_held(&local->chanctx_mtx));
74 	if (!conf)
75 		return NULL;
76 
77 	return container_of(conf, struct ieee80211_chanctx, conf);
78 }
79 
80 static const struct cfg80211_chan_def *
81 ieee80211_chanctx_reserved_chandef(struct ieee80211_local *local,
82 				   struct ieee80211_chanctx *ctx,
83 				   const struct cfg80211_chan_def *compat)
84 {
85 	struct ieee80211_sub_if_data *sdata;
86 
87 	lockdep_assert_held(&local->chanctx_mtx);
88 
89 	list_for_each_entry(sdata, &ctx->reserved_vifs,
90 			    reserved_chanctx_list) {
91 		if (!compat)
92 			compat = &sdata->reserved_chandef;
93 
94 		compat = cfg80211_chandef_compatible(&sdata->reserved_chandef,
95 						     compat);
96 		if (!compat)
97 			break;
98 	}
99 
100 	return compat;
101 }
102 
103 static const struct cfg80211_chan_def *
104 ieee80211_chanctx_non_reserved_chandef(struct ieee80211_local *local,
105 				       struct ieee80211_chanctx *ctx,
106 				       const struct cfg80211_chan_def *compat)
107 {
108 	struct ieee80211_sub_if_data *sdata;
109 
110 	lockdep_assert_held(&local->chanctx_mtx);
111 
112 	list_for_each_entry(sdata, &ctx->assigned_vifs,
113 			    assigned_chanctx_list) {
114 		if (sdata->reserved_chanctx != NULL)
115 			continue;
116 
117 		if (!compat)
118 			compat = &sdata->vif.bss_conf.chandef;
119 
120 		compat = cfg80211_chandef_compatible(
121 				&sdata->vif.bss_conf.chandef, compat);
122 		if (!compat)
123 			break;
124 	}
125 
126 	return compat;
127 }
128 
129 static const struct cfg80211_chan_def *
130 ieee80211_chanctx_combined_chandef(struct ieee80211_local *local,
131 				   struct ieee80211_chanctx *ctx,
132 				   const struct cfg80211_chan_def *compat)
133 {
134 	lockdep_assert_held(&local->chanctx_mtx);
135 
136 	compat = ieee80211_chanctx_reserved_chandef(local, ctx, compat);
137 	if (!compat)
138 		return NULL;
139 
140 	compat = ieee80211_chanctx_non_reserved_chandef(local, ctx, compat);
141 	if (!compat)
142 		return NULL;
143 
144 	return compat;
145 }
146 
147 static bool
148 ieee80211_chanctx_can_reserve_chandef(struct ieee80211_local *local,
149 				      struct ieee80211_chanctx *ctx,
150 				      const struct cfg80211_chan_def *def)
151 {
152 	lockdep_assert_held(&local->chanctx_mtx);
153 
154 	if (ieee80211_chanctx_combined_chandef(local, ctx, def))
155 		return true;
156 
157 	if (!list_empty(&ctx->reserved_vifs) &&
158 	    ieee80211_chanctx_reserved_chandef(local, ctx, def))
159 		return true;
160 
161 	return false;
162 }
163 
164 static struct ieee80211_chanctx *
165 ieee80211_find_reservation_chanctx(struct ieee80211_local *local,
166 				   const struct cfg80211_chan_def *chandef,
167 				   enum ieee80211_chanctx_mode mode)
168 {
169 	struct ieee80211_chanctx *ctx;
170 
171 	lockdep_assert_held(&local->chanctx_mtx);
172 
173 	if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
174 		return NULL;
175 
176 	list_for_each_entry(ctx, &local->chanctx_list, list) {
177 		if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
178 			continue;
179 
180 		if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
181 			continue;
182 
183 		if (!ieee80211_chanctx_can_reserve_chandef(local, ctx,
184 							   chandef))
185 			continue;
186 
187 		return ctx;
188 	}
189 
190 	return NULL;
191 }
192 
193 static enum nl80211_chan_width ieee80211_get_sta_bw(struct ieee80211_sta *sta)
194 {
195 	switch (sta->bandwidth) {
196 	case IEEE80211_STA_RX_BW_20:
197 		if (sta->ht_cap.ht_supported)
198 			return NL80211_CHAN_WIDTH_20;
199 		else
200 			return NL80211_CHAN_WIDTH_20_NOHT;
201 	case IEEE80211_STA_RX_BW_40:
202 		return NL80211_CHAN_WIDTH_40;
203 	case IEEE80211_STA_RX_BW_80:
204 		return NL80211_CHAN_WIDTH_80;
205 	case IEEE80211_STA_RX_BW_160:
206 		/*
207 		 * This applied for both 160 and 80+80. since we use
208 		 * the returned value to consider degradation of
209 		 * ctx->conf.min_def, we have to make sure to take
210 		 * the bigger one (NL80211_CHAN_WIDTH_160).
211 		 * Otherwise we might try degrading even when not
212 		 * needed, as the max required sta_bw returned (80+80)
213 		 * might be smaller than the configured bw (160).
214 		 */
215 		return NL80211_CHAN_WIDTH_160;
216 	default:
217 		WARN_ON(1);
218 		return NL80211_CHAN_WIDTH_20;
219 	}
220 }
221 
222 static enum nl80211_chan_width
223 ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata)
224 {
225 	enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
226 	struct sta_info *sta;
227 
228 	rcu_read_lock();
229 	list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
230 		if (sdata != sta->sdata &&
231 		    !(sta->sdata->bss && sta->sdata->bss == sdata->bss))
232 			continue;
233 
234 		if (!sta->uploaded)
235 			continue;
236 
237 		max_bw = max(max_bw, ieee80211_get_sta_bw(&sta->sta));
238 	}
239 	rcu_read_unlock();
240 
241 	return max_bw;
242 }
243 
244 static enum nl80211_chan_width
245 ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
246 				      struct ieee80211_chanctx_conf *conf)
247 {
248 	struct ieee80211_sub_if_data *sdata;
249 	enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
250 
251 	rcu_read_lock();
252 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
253 		struct ieee80211_vif *vif = &sdata->vif;
254 		enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT;
255 
256 		if (!ieee80211_sdata_running(sdata))
257 			continue;
258 
259 		if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
260 			continue;
261 
262 		switch (vif->type) {
263 		case NL80211_IFTYPE_AP:
264 		case NL80211_IFTYPE_AP_VLAN:
265 			width = ieee80211_get_max_required_bw(sdata);
266 			break;
267 		case NL80211_IFTYPE_P2P_DEVICE:
268 			continue;
269 		case NL80211_IFTYPE_STATION:
270 		case NL80211_IFTYPE_ADHOC:
271 		case NL80211_IFTYPE_WDS:
272 		case NL80211_IFTYPE_MESH_POINT:
273 		case NL80211_IFTYPE_OCB:
274 			width = vif->bss_conf.chandef.width;
275 			break;
276 		case NL80211_IFTYPE_UNSPECIFIED:
277 		case NUM_NL80211_IFTYPES:
278 		case NL80211_IFTYPE_MONITOR:
279 		case NL80211_IFTYPE_P2P_CLIENT:
280 		case NL80211_IFTYPE_P2P_GO:
281 			WARN_ON_ONCE(1);
282 		}
283 		max_bw = max(max_bw, width);
284 	}
285 
286 	/* use the configured bandwidth in case of monitor interface */
287 	sdata = rcu_dereference(local->monitor_sdata);
288 	if (sdata && rcu_access_pointer(sdata->vif.chanctx_conf) == conf)
289 		max_bw = max(max_bw, conf->def.width);
290 
291 	rcu_read_unlock();
292 
293 	return max_bw;
294 }
295 
296 /*
297  * recalc the min required chan width of the channel context, which is
298  * the max of min required widths of all the interfaces bound to this
299  * channel context.
300  */
301 void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
302 				      struct ieee80211_chanctx *ctx)
303 {
304 	enum nl80211_chan_width max_bw;
305 	struct cfg80211_chan_def min_def;
306 
307 	lockdep_assert_held(&local->chanctx_mtx);
308 
309 	/* don't optimize 5MHz, 10MHz, and radar_enabled confs */
310 	if (ctx->conf.def.width == NL80211_CHAN_WIDTH_5 ||
311 	    ctx->conf.def.width == NL80211_CHAN_WIDTH_10 ||
312 	    ctx->conf.radar_enabled) {
313 		ctx->conf.min_def = ctx->conf.def;
314 		return;
315 	}
316 
317 	max_bw = ieee80211_get_chanctx_max_required_bw(local, &ctx->conf);
318 
319 	/* downgrade chandef up to max_bw */
320 	min_def = ctx->conf.def;
321 	while (min_def.width > max_bw)
322 		ieee80211_chandef_downgrade(&min_def);
323 
324 	if (cfg80211_chandef_identical(&ctx->conf.min_def, &min_def))
325 		return;
326 
327 	ctx->conf.min_def = min_def;
328 	if (!ctx->driver_present)
329 		return;
330 
331 	drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_MIN_WIDTH);
332 }
333 
334 static void ieee80211_change_chanctx(struct ieee80211_local *local,
335 				     struct ieee80211_chanctx *ctx,
336 				     const struct cfg80211_chan_def *chandef)
337 {
338 	if (cfg80211_chandef_identical(&ctx->conf.def, chandef))
339 		return;
340 
341 	WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
342 
343 	ctx->conf.def = *chandef;
344 	drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
345 	ieee80211_recalc_chanctx_min_def(local, ctx);
346 
347 	if (!local->use_chanctx) {
348 		local->_oper_chandef = *chandef;
349 		ieee80211_hw_config(local, 0);
350 	}
351 }
352 
353 static struct ieee80211_chanctx *
354 ieee80211_find_chanctx(struct ieee80211_local *local,
355 		       const struct cfg80211_chan_def *chandef,
356 		       enum ieee80211_chanctx_mode mode)
357 {
358 	struct ieee80211_chanctx *ctx;
359 
360 	lockdep_assert_held(&local->chanctx_mtx);
361 
362 	if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
363 		return NULL;
364 
365 	list_for_each_entry(ctx, &local->chanctx_list, list) {
366 		const struct cfg80211_chan_def *compat;
367 
368 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACE_NONE)
369 			continue;
370 
371 		if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
372 			continue;
373 
374 		compat = cfg80211_chandef_compatible(&ctx->conf.def, chandef);
375 		if (!compat)
376 			continue;
377 
378 		compat = ieee80211_chanctx_reserved_chandef(local, ctx,
379 							    compat);
380 		if (!compat)
381 			continue;
382 
383 		ieee80211_change_chanctx(local, ctx, compat);
384 
385 		return ctx;
386 	}
387 
388 	return NULL;
389 }
390 
391 static bool ieee80211_is_radar_required(struct ieee80211_local *local)
392 {
393 	struct ieee80211_sub_if_data *sdata;
394 
395 	lockdep_assert_held(&local->mtx);
396 
397 	rcu_read_lock();
398 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
399 		if (sdata->radar_required) {
400 			rcu_read_unlock();
401 			return true;
402 		}
403 	}
404 	rcu_read_unlock();
405 
406 	return false;
407 }
408 
409 static struct ieee80211_chanctx *
410 ieee80211_alloc_chanctx(struct ieee80211_local *local,
411 			const struct cfg80211_chan_def *chandef,
412 			enum ieee80211_chanctx_mode mode)
413 {
414 	struct ieee80211_chanctx *ctx;
415 
416 	lockdep_assert_held(&local->chanctx_mtx);
417 
418 	ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL);
419 	if (!ctx)
420 		return NULL;
421 
422 	INIT_LIST_HEAD(&ctx->assigned_vifs);
423 	INIT_LIST_HEAD(&ctx->reserved_vifs);
424 	ctx->conf.def = *chandef;
425 	ctx->conf.rx_chains_static = 1;
426 	ctx->conf.rx_chains_dynamic = 1;
427 	ctx->mode = mode;
428 	ctx->conf.radar_enabled = ieee80211_is_radar_required(local);
429 	ieee80211_recalc_chanctx_min_def(local, ctx);
430 
431 	return ctx;
432 }
433 
434 static int ieee80211_add_chanctx(struct ieee80211_local *local,
435 				 struct ieee80211_chanctx *ctx)
436 {
437 	u32 changed;
438 	int err;
439 
440 	lockdep_assert_held(&local->mtx);
441 	lockdep_assert_held(&local->chanctx_mtx);
442 
443 	if (!local->use_chanctx)
444 		local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
445 
446 	/* turn idle off *before* setting channel -- some drivers need that */
447 	changed = ieee80211_idle_off(local);
448 	if (changed)
449 		ieee80211_hw_config(local, changed);
450 
451 	if (!local->use_chanctx) {
452 		local->_oper_chandef = ctx->conf.def;
453 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
454 	} else {
455 		err = drv_add_chanctx(local, ctx);
456 		if (err) {
457 			ieee80211_recalc_idle(local);
458 			return err;
459 		}
460 	}
461 
462 	return 0;
463 }
464 
465 static struct ieee80211_chanctx *
466 ieee80211_new_chanctx(struct ieee80211_local *local,
467 		      const struct cfg80211_chan_def *chandef,
468 		      enum ieee80211_chanctx_mode mode)
469 {
470 	struct ieee80211_chanctx *ctx;
471 	int err;
472 
473 	lockdep_assert_held(&local->mtx);
474 	lockdep_assert_held(&local->chanctx_mtx);
475 
476 	ctx = ieee80211_alloc_chanctx(local, chandef, mode);
477 	if (!ctx)
478 		return ERR_PTR(-ENOMEM);
479 
480 	err = ieee80211_add_chanctx(local, ctx);
481 	if (err) {
482 		kfree(ctx);
483 		return ERR_PTR(err);
484 	}
485 
486 	list_add_rcu(&ctx->list, &local->chanctx_list);
487 	return ctx;
488 }
489 
490 static void ieee80211_del_chanctx(struct ieee80211_local *local,
491 				  struct ieee80211_chanctx *ctx)
492 {
493 	lockdep_assert_held(&local->chanctx_mtx);
494 
495 	if (!local->use_chanctx) {
496 		struct cfg80211_chan_def *chandef = &local->_oper_chandef;
497 		chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
498 		chandef->center_freq1 = chandef->chan->center_freq;
499 		chandef->center_freq2 = 0;
500 
501 		/* NOTE: Disabling radar is only valid here for
502 		 * single channel context. To be sure, check it ...
503 		 */
504 		WARN_ON(local->hw.conf.radar_enabled &&
505 			!list_empty(&local->chanctx_list));
506 
507 		local->hw.conf.radar_enabled = false;
508 
509 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
510 	} else {
511 		drv_remove_chanctx(local, ctx);
512 	}
513 
514 	ieee80211_recalc_idle(local);
515 }
516 
517 static void ieee80211_free_chanctx(struct ieee80211_local *local,
518 				   struct ieee80211_chanctx *ctx)
519 {
520 	lockdep_assert_held(&local->chanctx_mtx);
521 
522 	WARN_ON_ONCE(ieee80211_chanctx_refcount(local, ctx) != 0);
523 
524 	list_del_rcu(&ctx->list);
525 	ieee80211_del_chanctx(local, ctx);
526 	kfree_rcu(ctx, rcu_head);
527 }
528 
529 static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
530 					      struct ieee80211_chanctx *ctx)
531 {
532 	struct ieee80211_chanctx_conf *conf = &ctx->conf;
533 	struct ieee80211_sub_if_data *sdata;
534 	const struct cfg80211_chan_def *compat = NULL;
535 
536 	lockdep_assert_held(&local->chanctx_mtx);
537 
538 	rcu_read_lock();
539 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
540 
541 		if (!ieee80211_sdata_running(sdata))
542 			continue;
543 		if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
544 			continue;
545 		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
546 			continue;
547 
548 		if (!compat)
549 			compat = &sdata->vif.bss_conf.chandef;
550 
551 		compat = cfg80211_chandef_compatible(
552 				&sdata->vif.bss_conf.chandef, compat);
553 		if (WARN_ON_ONCE(!compat))
554 			break;
555 	}
556 	rcu_read_unlock();
557 
558 	if (!compat)
559 		return;
560 
561 	ieee80211_change_chanctx(local, ctx, compat);
562 }
563 
564 static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
565 					   struct ieee80211_chanctx *chanctx)
566 {
567 	bool radar_enabled;
568 
569 	lockdep_assert_held(&local->chanctx_mtx);
570 	/* for setting local->radar_detect_enabled */
571 	lockdep_assert_held(&local->mtx);
572 
573 	radar_enabled = ieee80211_is_radar_required(local);
574 
575 	if (radar_enabled == chanctx->conf.radar_enabled)
576 		return;
577 
578 	chanctx->conf.radar_enabled = radar_enabled;
579 	local->radar_detect_enabled = chanctx->conf.radar_enabled;
580 
581 	if (!local->use_chanctx) {
582 		local->hw.conf.radar_enabled = chanctx->conf.radar_enabled;
583 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
584 	}
585 
586 	drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
587 }
588 
589 static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
590 					struct ieee80211_chanctx *new_ctx)
591 {
592 	struct ieee80211_local *local = sdata->local;
593 	struct ieee80211_chanctx_conf *conf;
594 	struct ieee80211_chanctx *curr_ctx = NULL;
595 	int ret = 0;
596 
597 	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
598 					 lockdep_is_held(&local->chanctx_mtx));
599 
600 	if (conf) {
601 		curr_ctx = container_of(conf, struct ieee80211_chanctx, conf);
602 
603 		drv_unassign_vif_chanctx(local, sdata, curr_ctx);
604 		conf = NULL;
605 		list_del(&sdata->assigned_chanctx_list);
606 	}
607 
608 	if (new_ctx) {
609 		ret = drv_assign_vif_chanctx(local, sdata, new_ctx);
610 		if (ret)
611 			goto out;
612 
613 		conf = &new_ctx->conf;
614 		list_add(&sdata->assigned_chanctx_list,
615 			 &new_ctx->assigned_vifs);
616 	}
617 
618 out:
619 	rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
620 
621 	sdata->vif.bss_conf.idle = !conf;
622 
623 	if (curr_ctx && ieee80211_chanctx_num_assigned(local, curr_ctx) > 0) {
624 		ieee80211_recalc_chanctx_chantype(local, curr_ctx);
625 		ieee80211_recalc_smps_chanctx(local, curr_ctx);
626 		ieee80211_recalc_radar_chanctx(local, curr_ctx);
627 		ieee80211_recalc_chanctx_min_def(local, curr_ctx);
628 	}
629 
630 	if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) {
631 		ieee80211_recalc_txpower(sdata);
632 		ieee80211_recalc_chanctx_min_def(local, new_ctx);
633 	}
634 
635 	if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
636 	    sdata->vif.type != NL80211_IFTYPE_MONITOR)
637 		ieee80211_bss_info_change_notify(sdata,
638 						 BSS_CHANGED_IDLE);
639 
640 	return ret;
641 }
642 
643 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
644 				   struct ieee80211_chanctx *chanctx)
645 {
646 	struct ieee80211_sub_if_data *sdata;
647 	u8 rx_chains_static, rx_chains_dynamic;
648 
649 	lockdep_assert_held(&local->chanctx_mtx);
650 
651 	rx_chains_static = 1;
652 	rx_chains_dynamic = 1;
653 
654 	rcu_read_lock();
655 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
656 		u8 needed_static, needed_dynamic;
657 
658 		if (!ieee80211_sdata_running(sdata))
659 			continue;
660 
661 		if (rcu_access_pointer(sdata->vif.chanctx_conf) !=
662 						&chanctx->conf)
663 			continue;
664 
665 		switch (sdata->vif.type) {
666 		case NL80211_IFTYPE_P2P_DEVICE:
667 			continue;
668 		case NL80211_IFTYPE_STATION:
669 			if (!sdata->u.mgd.associated)
670 				continue;
671 			break;
672 		case NL80211_IFTYPE_AP_VLAN:
673 			continue;
674 		case NL80211_IFTYPE_AP:
675 		case NL80211_IFTYPE_ADHOC:
676 		case NL80211_IFTYPE_WDS:
677 		case NL80211_IFTYPE_MESH_POINT:
678 		case NL80211_IFTYPE_OCB:
679 			break;
680 		default:
681 			WARN_ON_ONCE(1);
682 		}
683 
684 		switch (sdata->smps_mode) {
685 		default:
686 			WARN_ONCE(1, "Invalid SMPS mode %d\n",
687 				  sdata->smps_mode);
688 			/* fall through */
689 		case IEEE80211_SMPS_OFF:
690 			needed_static = sdata->needed_rx_chains;
691 			needed_dynamic = sdata->needed_rx_chains;
692 			break;
693 		case IEEE80211_SMPS_DYNAMIC:
694 			needed_static = 1;
695 			needed_dynamic = sdata->needed_rx_chains;
696 			break;
697 		case IEEE80211_SMPS_STATIC:
698 			needed_static = 1;
699 			needed_dynamic = 1;
700 			break;
701 		}
702 
703 		rx_chains_static = max(rx_chains_static, needed_static);
704 		rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
705 	}
706 
707 	/* Disable SMPS for the monitor interface */
708 	sdata = rcu_dereference(local->monitor_sdata);
709 	if (sdata &&
710 	    rcu_access_pointer(sdata->vif.chanctx_conf) == &chanctx->conf)
711 		rx_chains_dynamic = rx_chains_static = local->rx_chains;
712 
713 	rcu_read_unlock();
714 
715 	if (!local->use_chanctx) {
716 		if (rx_chains_static > 1)
717 			local->smps_mode = IEEE80211_SMPS_OFF;
718 		else if (rx_chains_dynamic > 1)
719 			local->smps_mode = IEEE80211_SMPS_DYNAMIC;
720 		else
721 			local->smps_mode = IEEE80211_SMPS_STATIC;
722 		ieee80211_hw_config(local, 0);
723 	}
724 
725 	if (rx_chains_static == chanctx->conf.rx_chains_static &&
726 	    rx_chains_dynamic == chanctx->conf.rx_chains_dynamic)
727 		return;
728 
729 	chanctx->conf.rx_chains_static = rx_chains_static;
730 	chanctx->conf.rx_chains_dynamic = rx_chains_dynamic;
731 	drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
732 }
733 
734 static void
735 __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
736 				      bool clear)
737 {
738 	struct ieee80211_local *local __maybe_unused = sdata->local;
739 	struct ieee80211_sub_if_data *vlan;
740 	struct ieee80211_chanctx_conf *conf;
741 
742 	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
743 		return;
744 
745 	lockdep_assert_held(&local->mtx);
746 
747 	/* Check that conf exists, even when clearing this function
748 	 * must be called with the AP's channel context still there
749 	 * as it would otherwise cause VLANs to have an invalid
750 	 * channel context pointer for a while, possibly pointing
751 	 * to a channel context that has already been freed.
752 	 */
753 	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
754 					 lockdep_is_held(&local->chanctx_mtx));
755 	WARN_ON(!conf);
756 
757 	if (clear)
758 		conf = NULL;
759 
760 	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
761 		rcu_assign_pointer(vlan->vif.chanctx_conf, conf);
762 }
763 
764 void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
765 					 bool clear)
766 {
767 	struct ieee80211_local *local = sdata->local;
768 
769 	mutex_lock(&local->chanctx_mtx);
770 
771 	__ieee80211_vif_copy_chanctx_to_vlans(sdata, clear);
772 
773 	mutex_unlock(&local->chanctx_mtx);
774 }
775 
776 int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data *sdata)
777 {
778 	struct ieee80211_chanctx *ctx = sdata->reserved_chanctx;
779 
780 	lockdep_assert_held(&sdata->local->chanctx_mtx);
781 
782 	if (WARN_ON(!ctx))
783 		return -EINVAL;
784 
785 	list_del(&sdata->reserved_chanctx_list);
786 	sdata->reserved_chanctx = NULL;
787 
788 	if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0) {
789 		if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
790 			if (WARN_ON(!ctx->replace_ctx))
791 				return -EINVAL;
792 
793 			WARN_ON(ctx->replace_ctx->replace_state !=
794 			        IEEE80211_CHANCTX_WILL_BE_REPLACED);
795 			WARN_ON(ctx->replace_ctx->replace_ctx != ctx);
796 
797 			ctx->replace_ctx->replace_ctx = NULL;
798 			ctx->replace_ctx->replace_state =
799 					IEEE80211_CHANCTX_REPLACE_NONE;
800 
801 			list_del_rcu(&ctx->list);
802 			kfree_rcu(ctx, rcu_head);
803 		} else {
804 			ieee80211_free_chanctx(sdata->local, ctx);
805 		}
806 	}
807 
808 	return 0;
809 }
810 
811 int ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
812 				  const struct cfg80211_chan_def *chandef,
813 				  enum ieee80211_chanctx_mode mode,
814 				  bool radar_required)
815 {
816 	struct ieee80211_local *local = sdata->local;
817 	struct ieee80211_chanctx *new_ctx, *curr_ctx, *ctx;
818 
819 	lockdep_assert_held(&local->chanctx_mtx);
820 
821 	curr_ctx = ieee80211_vif_get_chanctx(sdata);
822 	if (curr_ctx && local->use_chanctx && !local->ops->switch_vif_chanctx)
823 		return -ENOTSUPP;
824 
825 	new_ctx = ieee80211_find_reservation_chanctx(local, chandef, mode);
826 	if (!new_ctx) {
827 		if (ieee80211_can_create_new_chanctx(local)) {
828 			new_ctx = ieee80211_new_chanctx(local, chandef, mode);
829 			if (IS_ERR(new_ctx))
830 				return PTR_ERR(new_ctx);
831 		} else {
832 			if (!curr_ctx ||
833 			    (curr_ctx->replace_state ==
834 			     IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
835 			    !list_empty(&curr_ctx->reserved_vifs)) {
836 				/*
837 				 * Another vif already requested this context
838 				 * for a reservation. Find another one hoping
839 				 * all vifs assigned to it will also switch
840 				 * soon enough.
841 				 *
842 				 * TODO: This needs a little more work as some
843 				 * cases (more than 2 chanctx capable devices)
844 				 * may fail which could otherwise succeed
845 				 * provided some channel context juggling was
846 				 * performed.
847 				 *
848 				 * Consider ctx1..3, vif1..6, each ctx has 2
849 				 * vifs. vif1 and vif2 from ctx1 request new
850 				 * different chandefs starting 2 in-place
851 				 * reserations with ctx4 and ctx5 replacing
852 				 * ctx1 and ctx2 respectively. Next vif5 and
853 				 * vif6 from ctx3 reserve ctx4. If vif3 and
854 				 * vif4 remain on ctx2 as they are then this
855 				 * fails unless `replace_ctx` from ctx5 is
856 				 * replaced with ctx3.
857 				 */
858 				list_for_each_entry(ctx, &local->chanctx_list,
859 						    list) {
860 					if (ctx->replace_state !=
861 					    IEEE80211_CHANCTX_REPLACE_NONE)
862 						continue;
863 
864 					if (!list_empty(&ctx->reserved_vifs))
865 						continue;
866 
867 					curr_ctx = ctx;
868 					break;
869 				}
870 			}
871 
872 			/*
873 			 * If that's true then all available contexts already
874 			 * have reservations and cannot be used.
875 			 */
876 			if (!curr_ctx ||
877 			    (curr_ctx->replace_state ==
878 			     IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
879 			    !list_empty(&curr_ctx->reserved_vifs))
880 				return -EBUSY;
881 
882 			new_ctx = ieee80211_alloc_chanctx(local, chandef, mode);
883 			if (!new_ctx)
884 				return -ENOMEM;
885 
886 			new_ctx->replace_ctx = curr_ctx;
887 			new_ctx->replace_state =
888 					IEEE80211_CHANCTX_REPLACES_OTHER;
889 
890 			curr_ctx->replace_ctx = new_ctx;
891 			curr_ctx->replace_state =
892 					IEEE80211_CHANCTX_WILL_BE_REPLACED;
893 
894 			list_add_rcu(&new_ctx->list, &local->chanctx_list);
895 		}
896 	}
897 
898 	list_add(&sdata->reserved_chanctx_list, &new_ctx->reserved_vifs);
899 	sdata->reserved_chanctx = new_ctx;
900 	sdata->reserved_chandef = *chandef;
901 	sdata->reserved_radar_required = radar_required;
902 	sdata->reserved_ready = false;
903 
904 	return 0;
905 }
906 
907 static void
908 ieee80211_vif_chanctx_reservation_complete(struct ieee80211_sub_if_data *sdata)
909 {
910 	switch (sdata->vif.type) {
911 	case NL80211_IFTYPE_ADHOC:
912 	case NL80211_IFTYPE_AP:
913 	case NL80211_IFTYPE_MESH_POINT:
914 	case NL80211_IFTYPE_OCB:
915 		ieee80211_queue_work(&sdata->local->hw,
916 				     &sdata->csa_finalize_work);
917 		break;
918 	case NL80211_IFTYPE_STATION:
919 		ieee80211_queue_work(&sdata->local->hw,
920 				     &sdata->u.mgd.chswitch_work);
921 		break;
922 	case NL80211_IFTYPE_UNSPECIFIED:
923 	case NL80211_IFTYPE_AP_VLAN:
924 	case NL80211_IFTYPE_WDS:
925 	case NL80211_IFTYPE_MONITOR:
926 	case NL80211_IFTYPE_P2P_CLIENT:
927 	case NL80211_IFTYPE_P2P_GO:
928 	case NL80211_IFTYPE_P2P_DEVICE:
929 	case NUM_NL80211_IFTYPES:
930 		WARN_ON(1);
931 		break;
932 	}
933 }
934 
935 static void
936 ieee80211_vif_update_chandef(struct ieee80211_sub_if_data *sdata,
937 			     const struct cfg80211_chan_def *chandef)
938 {
939 	struct ieee80211_sub_if_data *vlan;
940 
941 	sdata->vif.bss_conf.chandef = *chandef;
942 
943 	if (sdata->vif.type != NL80211_IFTYPE_AP)
944 		return;
945 
946 	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
947 		vlan->vif.bss_conf.chandef = *chandef;
948 }
949 
950 static int
951 ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata)
952 {
953 	struct ieee80211_local *local = sdata->local;
954 	struct ieee80211_vif_chanctx_switch vif_chsw[1] = {};
955 	struct ieee80211_chanctx *old_ctx, *new_ctx;
956 	const struct cfg80211_chan_def *chandef;
957 	u32 changed = 0;
958 	int err;
959 
960 	lockdep_assert_held(&local->mtx);
961 	lockdep_assert_held(&local->chanctx_mtx);
962 
963 	new_ctx = sdata->reserved_chanctx;
964 	old_ctx = ieee80211_vif_get_chanctx(sdata);
965 
966 	if (WARN_ON(!sdata->reserved_ready))
967 		return -EBUSY;
968 
969 	if (WARN_ON(!new_ctx))
970 		return -EINVAL;
971 
972 	if (WARN_ON(!old_ctx))
973 		return -EINVAL;
974 
975 	if (WARN_ON(new_ctx->replace_state ==
976 		    IEEE80211_CHANCTX_REPLACES_OTHER))
977 		return -EINVAL;
978 
979 	chandef = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
980 				&sdata->reserved_chandef);
981 	if (WARN_ON(!chandef))
982 		return -EINVAL;
983 
984 	vif_chsw[0].vif = &sdata->vif;
985 	vif_chsw[0].old_ctx = &old_ctx->conf;
986 	vif_chsw[0].new_ctx = &new_ctx->conf;
987 
988 	list_del(&sdata->reserved_chanctx_list);
989 	sdata->reserved_chanctx = NULL;
990 
991 	err = drv_switch_vif_chanctx(local, vif_chsw, 1,
992 				     CHANCTX_SWMODE_REASSIGN_VIF);
993 	if (err) {
994 		if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
995 			ieee80211_free_chanctx(local, new_ctx);
996 
997 		goto out;
998 	}
999 
1000 	list_move(&sdata->assigned_chanctx_list, &new_ctx->assigned_vifs);
1001 	rcu_assign_pointer(sdata->vif.chanctx_conf, &new_ctx->conf);
1002 
1003 	if (sdata->vif.type == NL80211_IFTYPE_AP)
1004 		__ieee80211_vif_copy_chanctx_to_vlans(sdata, false);
1005 
1006 	if (ieee80211_chanctx_refcount(local, old_ctx) == 0)
1007 		ieee80211_free_chanctx(local, old_ctx);
1008 
1009 	if (sdata->vif.bss_conf.chandef.width != sdata->reserved_chandef.width)
1010 		changed = BSS_CHANGED_BANDWIDTH;
1011 
1012 	ieee80211_vif_update_chandef(sdata, &sdata->reserved_chandef);
1013 
1014 	ieee80211_recalc_smps_chanctx(local, new_ctx);
1015 	ieee80211_recalc_radar_chanctx(local, new_ctx);
1016 	ieee80211_recalc_chanctx_min_def(local, new_ctx);
1017 
1018 	if (changed)
1019 		ieee80211_bss_info_change_notify(sdata, changed);
1020 
1021 out:
1022 	ieee80211_vif_chanctx_reservation_complete(sdata);
1023 	return err;
1024 }
1025 
1026 static int
1027 ieee80211_vif_use_reserved_assign(struct ieee80211_sub_if_data *sdata)
1028 {
1029 	struct ieee80211_local *local = sdata->local;
1030 	struct ieee80211_chanctx *old_ctx, *new_ctx;
1031 	const struct cfg80211_chan_def *chandef;
1032 	int err;
1033 
1034 	old_ctx = ieee80211_vif_get_chanctx(sdata);
1035 	new_ctx = sdata->reserved_chanctx;
1036 
1037 	if (WARN_ON(!sdata->reserved_ready))
1038 		return -EINVAL;
1039 
1040 	if (WARN_ON(old_ctx))
1041 		return -EINVAL;
1042 
1043 	if (WARN_ON(!new_ctx))
1044 		return -EINVAL;
1045 
1046 	if (WARN_ON(new_ctx->replace_state ==
1047 		    IEEE80211_CHANCTX_REPLACES_OTHER))
1048 		return -EINVAL;
1049 
1050 	chandef = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
1051 				&sdata->reserved_chandef);
1052 	if (WARN_ON(!chandef))
1053 		return -EINVAL;
1054 
1055 	list_del(&sdata->reserved_chanctx_list);
1056 	sdata->reserved_chanctx = NULL;
1057 
1058 	err = ieee80211_assign_vif_chanctx(sdata, new_ctx);
1059 	if (err) {
1060 		if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
1061 			ieee80211_free_chanctx(local, new_ctx);
1062 
1063 		goto out;
1064 	}
1065 
1066 out:
1067 	ieee80211_vif_chanctx_reservation_complete(sdata);
1068 	return err;
1069 }
1070 
1071 static bool
1072 ieee80211_vif_has_in_place_reservation(struct ieee80211_sub_if_data *sdata)
1073 {
1074 	struct ieee80211_chanctx *old_ctx, *new_ctx;
1075 
1076 	lockdep_assert_held(&sdata->local->chanctx_mtx);
1077 
1078 	new_ctx = sdata->reserved_chanctx;
1079 	old_ctx = ieee80211_vif_get_chanctx(sdata);
1080 
1081 	if (!old_ctx)
1082 		return false;
1083 
1084 	if (WARN_ON(!new_ctx))
1085 		return false;
1086 
1087 	if (old_ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
1088 		return false;
1089 
1090 	if (new_ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1091 		return false;
1092 
1093 	return true;
1094 }
1095 
1096 static int ieee80211_chsw_switch_hwconf(struct ieee80211_local *local,
1097 					struct ieee80211_chanctx *new_ctx)
1098 {
1099 	const struct cfg80211_chan_def *chandef;
1100 
1101 	lockdep_assert_held(&local->mtx);
1102 	lockdep_assert_held(&local->chanctx_mtx);
1103 
1104 	chandef = ieee80211_chanctx_reserved_chandef(local, new_ctx, NULL);
1105 	if (WARN_ON(!chandef))
1106 		return -EINVAL;
1107 
1108 	local->hw.conf.radar_enabled = new_ctx->conf.radar_enabled;
1109 	local->_oper_chandef = *chandef;
1110 	ieee80211_hw_config(local, 0);
1111 
1112 	return 0;
1113 }
1114 
1115 static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local,
1116 				      int n_vifs)
1117 {
1118 	struct ieee80211_vif_chanctx_switch *vif_chsw;
1119 	struct ieee80211_sub_if_data *sdata;
1120 	struct ieee80211_chanctx *ctx, *old_ctx;
1121 	int i, err;
1122 
1123 	lockdep_assert_held(&local->mtx);
1124 	lockdep_assert_held(&local->chanctx_mtx);
1125 
1126 	vif_chsw = kzalloc(sizeof(vif_chsw[0]) * n_vifs, GFP_KERNEL);
1127 	if (!vif_chsw)
1128 		return -ENOMEM;
1129 
1130 	i = 0;
1131 	list_for_each_entry(ctx, &local->chanctx_list, list) {
1132 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1133 			continue;
1134 
1135 		if (WARN_ON(!ctx->replace_ctx)) {
1136 			err = -EINVAL;
1137 			goto out;
1138 		}
1139 
1140 		list_for_each_entry(sdata, &ctx->reserved_vifs,
1141 				    reserved_chanctx_list) {
1142 			if (!ieee80211_vif_has_in_place_reservation(
1143 					sdata))
1144 				continue;
1145 
1146 			old_ctx = ieee80211_vif_get_chanctx(sdata);
1147 			vif_chsw[i].vif = &sdata->vif;
1148 			vif_chsw[i].old_ctx = &old_ctx->conf;
1149 			vif_chsw[i].new_ctx = &ctx->conf;
1150 
1151 			i++;
1152 		}
1153 	}
1154 
1155 	err = drv_switch_vif_chanctx(local, vif_chsw, n_vifs,
1156 				     CHANCTX_SWMODE_SWAP_CONTEXTS);
1157 
1158 out:
1159 	kfree(vif_chsw);
1160 	return err;
1161 }
1162 
1163 static int ieee80211_chsw_switch_ctxs(struct ieee80211_local *local)
1164 {
1165 	struct ieee80211_chanctx *ctx;
1166 	int err;
1167 
1168 	lockdep_assert_held(&local->mtx);
1169 	lockdep_assert_held(&local->chanctx_mtx);
1170 
1171 	list_for_each_entry(ctx, &local->chanctx_list, list) {
1172 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1173 			continue;
1174 
1175 		if (!list_empty(&ctx->replace_ctx->assigned_vifs))
1176 			continue;
1177 
1178 		ieee80211_del_chanctx(local, ctx->replace_ctx);
1179 		err = ieee80211_add_chanctx(local, ctx);
1180 		if (err)
1181 			goto err;
1182 	}
1183 
1184 	return 0;
1185 
1186 err:
1187 	WARN_ON(ieee80211_add_chanctx(local, ctx));
1188 	list_for_each_entry_continue_reverse(ctx, &local->chanctx_list, list) {
1189 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1190 			continue;
1191 
1192 		if (!list_empty(&ctx->replace_ctx->assigned_vifs))
1193 			continue;
1194 
1195 		ieee80211_del_chanctx(local, ctx);
1196 		WARN_ON(ieee80211_add_chanctx(local, ctx->replace_ctx));
1197 	}
1198 
1199 	return err;
1200 }
1201 
1202 static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
1203 {
1204 	struct ieee80211_sub_if_data *sdata, *sdata_tmp;
1205 	struct ieee80211_chanctx *ctx, *ctx_tmp, *old_ctx;
1206 	struct ieee80211_chanctx *new_ctx = NULL;
1207 	int i, err, n_assigned, n_reserved, n_ready;
1208 	int n_ctx = 0, n_vifs_switch = 0, n_vifs_assign = 0, n_vifs_ctxless = 0;
1209 
1210 	lockdep_assert_held(&local->mtx);
1211 	lockdep_assert_held(&local->chanctx_mtx);
1212 
1213 	/*
1214 	 * If there are 2 independent pairs of channel contexts performing
1215 	 * cross-switch of their vifs this code will still wait until both are
1216 	 * ready even though it could be possible to switch one before the
1217 	 * other is ready.
1218 	 *
1219 	 * For practical reasons and code simplicity just do a single huge
1220 	 * switch.
1221 	 */
1222 
1223 	/*
1224 	 * Verify if the reservation is still feasible.
1225 	 *  - if it's not then disconnect
1226 	 *  - if it is but not all vifs necessary are ready then defer
1227 	 */
1228 
1229 	list_for_each_entry(ctx, &local->chanctx_list, list) {
1230 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1231 			continue;
1232 
1233 		if (WARN_ON(!ctx->replace_ctx)) {
1234 			err = -EINVAL;
1235 			goto err;
1236 		}
1237 
1238 		if (!local->use_chanctx)
1239 			new_ctx = ctx;
1240 
1241 		n_ctx++;
1242 
1243 		n_assigned = 0;
1244 		n_reserved = 0;
1245 		n_ready = 0;
1246 
1247 		list_for_each_entry(sdata, &ctx->replace_ctx->assigned_vifs,
1248 				    assigned_chanctx_list) {
1249 			n_assigned++;
1250 			if (sdata->reserved_chanctx) {
1251 				n_reserved++;
1252 				if (sdata->reserved_ready)
1253 					n_ready++;
1254 			}
1255 		}
1256 
1257 		if (n_assigned != n_reserved) {
1258 			if (n_ready == n_reserved) {
1259 				wiphy_info(local->hw.wiphy,
1260 					   "channel context reservation cannot be finalized because some interfaces aren't switching\n");
1261 				err = -EBUSY;
1262 				goto err;
1263 			}
1264 
1265 			return -EAGAIN;
1266 		}
1267 
1268 		ctx->conf.radar_enabled = false;
1269 		list_for_each_entry(sdata, &ctx->reserved_vifs,
1270 				    reserved_chanctx_list) {
1271 			if (ieee80211_vif_has_in_place_reservation(sdata) &&
1272 			    !sdata->reserved_ready)
1273 				return -EAGAIN;
1274 
1275 			old_ctx = ieee80211_vif_get_chanctx(sdata);
1276 			if (old_ctx) {
1277 				if (old_ctx->replace_state ==
1278 				    IEEE80211_CHANCTX_WILL_BE_REPLACED)
1279 					n_vifs_switch++;
1280 				else
1281 					n_vifs_assign++;
1282 			} else {
1283 				n_vifs_ctxless++;
1284 			}
1285 
1286 			if (sdata->reserved_radar_required)
1287 				ctx->conf.radar_enabled = true;
1288 		}
1289 	}
1290 
1291 	if (WARN_ON(n_ctx == 0) ||
1292 	    WARN_ON(n_vifs_switch == 0 &&
1293 		    n_vifs_assign == 0 &&
1294 		    n_vifs_ctxless == 0) ||
1295 	    WARN_ON(n_ctx > 1 && !local->use_chanctx) ||
1296 	    WARN_ON(!new_ctx && !local->use_chanctx)) {
1297 		err = -EINVAL;
1298 		goto err;
1299 	}
1300 
1301 	/*
1302 	 * All necessary vifs are ready. Perform the switch now depending on
1303 	 * reservations and driver capabilities.
1304 	 */
1305 
1306 	if (local->use_chanctx) {
1307 		if (n_vifs_switch > 0) {
1308 			err = ieee80211_chsw_switch_vifs(local, n_vifs_switch);
1309 			if (err)
1310 				goto err;
1311 		}
1312 
1313 		if (n_vifs_assign > 0 || n_vifs_ctxless > 0) {
1314 			err = ieee80211_chsw_switch_ctxs(local);
1315 			if (err)
1316 				goto err;
1317 		}
1318 	} else {
1319 		err = ieee80211_chsw_switch_hwconf(local, new_ctx);
1320 		if (err)
1321 			goto err;
1322 	}
1323 
1324 	/*
1325 	 * Update all structures, values and pointers to point to new channel
1326 	 * context(s).
1327 	 */
1328 
1329 	i = 0;
1330 	list_for_each_entry(ctx, &local->chanctx_list, list) {
1331 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1332 			continue;
1333 
1334 		if (WARN_ON(!ctx->replace_ctx)) {
1335 			err = -EINVAL;
1336 			goto err;
1337 		}
1338 
1339 		list_for_each_entry(sdata, &ctx->reserved_vifs,
1340 				    reserved_chanctx_list) {
1341 			u32 changed = 0;
1342 
1343 			if (!ieee80211_vif_has_in_place_reservation(sdata))
1344 				continue;
1345 
1346 			rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf);
1347 
1348 			if (sdata->vif.type == NL80211_IFTYPE_AP)
1349 				__ieee80211_vif_copy_chanctx_to_vlans(sdata,
1350 								      false);
1351 
1352 			sdata->radar_required = sdata->reserved_radar_required;
1353 
1354 			if (sdata->vif.bss_conf.chandef.width !=
1355 			    sdata->reserved_chandef.width)
1356 				changed = BSS_CHANGED_BANDWIDTH;
1357 
1358 			ieee80211_vif_update_chandef(sdata, &sdata->reserved_chandef);
1359 			if (changed)
1360 				ieee80211_bss_info_change_notify(sdata,
1361 								 changed);
1362 
1363 			ieee80211_recalc_txpower(sdata);
1364 		}
1365 
1366 		ieee80211_recalc_chanctx_chantype(local, ctx);
1367 		ieee80211_recalc_smps_chanctx(local, ctx);
1368 		ieee80211_recalc_radar_chanctx(local, ctx);
1369 		ieee80211_recalc_chanctx_min_def(local, ctx);
1370 
1371 		list_for_each_entry_safe(sdata, sdata_tmp, &ctx->reserved_vifs,
1372 					 reserved_chanctx_list) {
1373 			if (ieee80211_vif_get_chanctx(sdata) != ctx)
1374 				continue;
1375 
1376 			list_del(&sdata->reserved_chanctx_list);
1377 			list_move(&sdata->assigned_chanctx_list,
1378 				  &ctx->assigned_vifs);
1379 			sdata->reserved_chanctx = NULL;
1380 
1381 			ieee80211_vif_chanctx_reservation_complete(sdata);
1382 		}
1383 
1384 		/*
1385 		 * This context might have been a dependency for an already
1386 		 * ready re-assign reservation interface that was deferred. Do
1387 		 * not propagate error to the caller though. The in-place
1388 		 * reservation for originally requested interface has already
1389 		 * succeeded at this point.
1390 		 */
1391 		list_for_each_entry_safe(sdata, sdata_tmp, &ctx->reserved_vifs,
1392 					 reserved_chanctx_list) {
1393 			if (WARN_ON(ieee80211_vif_has_in_place_reservation(
1394 					sdata)))
1395 				continue;
1396 
1397 			if (WARN_ON(sdata->reserved_chanctx != ctx))
1398 				continue;
1399 
1400 			if (!sdata->reserved_ready)
1401 				continue;
1402 
1403 			if (ieee80211_vif_get_chanctx(sdata))
1404 				err = ieee80211_vif_use_reserved_reassign(
1405 						sdata);
1406 			else
1407 				err = ieee80211_vif_use_reserved_assign(sdata);
1408 
1409 			if (err) {
1410 				sdata_info(sdata,
1411 					   "failed to finalize (re-)assign reservation (err=%d)\n",
1412 					   err);
1413 				ieee80211_vif_unreserve_chanctx(sdata);
1414 				cfg80211_stop_iface(local->hw.wiphy,
1415 						    &sdata->wdev,
1416 						    GFP_KERNEL);
1417 			}
1418 		}
1419 	}
1420 
1421 	/*
1422 	 * Finally free old contexts
1423 	 */
1424 
1425 	list_for_each_entry_safe(ctx, ctx_tmp, &local->chanctx_list, list) {
1426 		if (ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
1427 			continue;
1428 
1429 		ctx->replace_ctx->replace_ctx = NULL;
1430 		ctx->replace_ctx->replace_state =
1431 				IEEE80211_CHANCTX_REPLACE_NONE;
1432 
1433 		list_del_rcu(&ctx->list);
1434 		kfree_rcu(ctx, rcu_head);
1435 	}
1436 
1437 	return 0;
1438 
1439 err:
1440 	list_for_each_entry(ctx, &local->chanctx_list, list) {
1441 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1442 			continue;
1443 
1444 		list_for_each_entry_safe(sdata, sdata_tmp, &ctx->reserved_vifs,
1445 					 reserved_chanctx_list) {
1446 			ieee80211_vif_unreserve_chanctx(sdata);
1447 			ieee80211_vif_chanctx_reservation_complete(sdata);
1448 		}
1449 	}
1450 
1451 	return err;
1452 }
1453 
1454 static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
1455 {
1456 	struct ieee80211_local *local = sdata->local;
1457 	struct ieee80211_chanctx_conf *conf;
1458 	struct ieee80211_chanctx *ctx;
1459 	bool use_reserved_switch = false;
1460 
1461 	lockdep_assert_held(&local->chanctx_mtx);
1462 
1463 	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
1464 					 lockdep_is_held(&local->chanctx_mtx));
1465 	if (!conf)
1466 		return;
1467 
1468 	ctx = container_of(conf, struct ieee80211_chanctx, conf);
1469 
1470 	if (sdata->reserved_chanctx) {
1471 		if (sdata->reserved_chanctx->replace_state ==
1472 		    IEEE80211_CHANCTX_REPLACES_OTHER &&
1473 		    ieee80211_chanctx_num_reserved(local,
1474 						   sdata->reserved_chanctx) > 1)
1475 			use_reserved_switch = true;
1476 
1477 		ieee80211_vif_unreserve_chanctx(sdata);
1478 	}
1479 
1480 	ieee80211_assign_vif_chanctx(sdata, NULL);
1481 	if (ieee80211_chanctx_refcount(local, ctx) == 0)
1482 		ieee80211_free_chanctx(local, ctx);
1483 
1484 	/* Unreserving may ready an in-place reservation. */
1485 	if (use_reserved_switch)
1486 		ieee80211_vif_use_reserved_switch(local);
1487 }
1488 
1489 int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
1490 			      const struct cfg80211_chan_def *chandef,
1491 			      enum ieee80211_chanctx_mode mode)
1492 {
1493 	struct ieee80211_local *local = sdata->local;
1494 	struct ieee80211_chanctx *ctx;
1495 	u8 radar_detect_width = 0;
1496 	int ret;
1497 
1498 	lockdep_assert_held(&local->mtx);
1499 
1500 	WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
1501 
1502 	mutex_lock(&local->chanctx_mtx);
1503 
1504 	ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
1505 					    chandef,
1506 					    sdata->wdev.iftype);
1507 	if (ret < 0)
1508 		goto out;
1509 	if (ret > 0)
1510 		radar_detect_width = BIT(chandef->width);
1511 
1512 	sdata->radar_required = ret;
1513 
1514 	ret = ieee80211_check_combinations(sdata, chandef, mode,
1515 					   radar_detect_width);
1516 	if (ret < 0)
1517 		goto out;
1518 
1519 	__ieee80211_vif_release_channel(sdata);
1520 
1521 	ctx = ieee80211_find_chanctx(local, chandef, mode);
1522 	if (!ctx)
1523 		ctx = ieee80211_new_chanctx(local, chandef, mode);
1524 	if (IS_ERR(ctx)) {
1525 		ret = PTR_ERR(ctx);
1526 		goto out;
1527 	}
1528 
1529 	ieee80211_vif_update_chandef(sdata, chandef);
1530 
1531 	ret = ieee80211_assign_vif_chanctx(sdata, ctx);
1532 	if (ret) {
1533 		/* if assign fails refcount stays the same */
1534 		if (ieee80211_chanctx_refcount(local, ctx) == 0)
1535 			ieee80211_free_chanctx(local, ctx);
1536 		goto out;
1537 	}
1538 
1539 	ieee80211_recalc_smps_chanctx(local, ctx);
1540 	ieee80211_recalc_radar_chanctx(local, ctx);
1541  out:
1542 	mutex_unlock(&local->chanctx_mtx);
1543 	return ret;
1544 }
1545 
1546 int ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata)
1547 {
1548 	struct ieee80211_local *local = sdata->local;
1549 	struct ieee80211_chanctx *new_ctx;
1550 	struct ieee80211_chanctx *old_ctx;
1551 	int err;
1552 
1553 	lockdep_assert_held(&local->mtx);
1554 	lockdep_assert_held(&local->chanctx_mtx);
1555 
1556 	new_ctx = sdata->reserved_chanctx;
1557 	old_ctx = ieee80211_vif_get_chanctx(sdata);
1558 
1559 	if (WARN_ON(!new_ctx))
1560 		return -EINVAL;
1561 
1562 	if (WARN_ON(new_ctx->replace_state ==
1563 		    IEEE80211_CHANCTX_WILL_BE_REPLACED))
1564 		return -EINVAL;
1565 
1566 	if (WARN_ON(sdata->reserved_ready))
1567 		return -EINVAL;
1568 
1569 	sdata->reserved_ready = true;
1570 
1571 	if (new_ctx->replace_state == IEEE80211_CHANCTX_REPLACE_NONE) {
1572 		if (old_ctx)
1573 			err = ieee80211_vif_use_reserved_reassign(sdata);
1574 		else
1575 			err = ieee80211_vif_use_reserved_assign(sdata);
1576 
1577 		if (err)
1578 			return err;
1579 	}
1580 
1581 	/*
1582 	 * In-place reservation may need to be finalized now either if:
1583 	 *  a) sdata is taking part in the swapping itself and is the last one
1584 	 *  b) sdata has switched with a re-assign reservation to an existing
1585 	 *     context readying in-place switching of old_ctx
1586 	 *
1587 	 * In case of (b) do not propagate the error up because the requested
1588 	 * sdata already switched successfully. Just spill an extra warning.
1589 	 * The ieee80211_vif_use_reserved_switch() already stops all necessary
1590 	 * interfaces upon failure.
1591 	 */
1592 	if ((old_ctx &&
1593 	     old_ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
1594 	    new_ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
1595 		err = ieee80211_vif_use_reserved_switch(local);
1596 		if (err && err != -EAGAIN) {
1597 			if (new_ctx->replace_state ==
1598 			    IEEE80211_CHANCTX_REPLACES_OTHER)
1599 				return err;
1600 
1601 			wiphy_info(local->hw.wiphy,
1602 				   "depending in-place reservation failed (err=%d)\n",
1603 				   err);
1604 		}
1605 	}
1606 
1607 	return 0;
1608 }
1609 
1610 int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
1611 				   const struct cfg80211_chan_def *chandef,
1612 				   u32 *changed)
1613 {
1614 	struct ieee80211_local *local = sdata->local;
1615 	struct ieee80211_chanctx_conf *conf;
1616 	struct ieee80211_chanctx *ctx;
1617 	const struct cfg80211_chan_def *compat;
1618 	int ret;
1619 
1620 	if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
1621 				     IEEE80211_CHAN_DISABLED))
1622 		return -EINVAL;
1623 
1624 	mutex_lock(&local->chanctx_mtx);
1625 	if (cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef)) {
1626 		ret = 0;
1627 		goto out;
1628 	}
1629 
1630 	if (chandef->width == NL80211_CHAN_WIDTH_20_NOHT ||
1631 	    sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) {
1632 		ret = -EINVAL;
1633 		goto out;
1634 	}
1635 
1636 	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
1637 					 lockdep_is_held(&local->chanctx_mtx));
1638 	if (!conf) {
1639 		ret = -EINVAL;
1640 		goto out;
1641 	}
1642 
1643 	ctx = container_of(conf, struct ieee80211_chanctx, conf);
1644 
1645 	compat = cfg80211_chandef_compatible(&conf->def, chandef);
1646 	if (!compat) {
1647 		ret = -EINVAL;
1648 		goto out;
1649 	}
1650 
1651 	switch (ctx->replace_state) {
1652 	case IEEE80211_CHANCTX_REPLACE_NONE:
1653 		if (!ieee80211_chanctx_reserved_chandef(local, ctx, compat)) {
1654 			ret = -EBUSY;
1655 			goto out;
1656 		}
1657 		break;
1658 	case IEEE80211_CHANCTX_WILL_BE_REPLACED:
1659 		/* TODO: Perhaps the bandwidth change could be treated as a
1660 		 * reservation itself? */
1661 		ret = -EBUSY;
1662 		goto out;
1663 	case IEEE80211_CHANCTX_REPLACES_OTHER:
1664 		/* channel context that is going to replace another channel
1665 		 * context doesn't really exist and shouldn't be assigned
1666 		 * anywhere yet */
1667 		WARN_ON(1);
1668 		break;
1669 	}
1670 
1671 	ieee80211_vif_update_chandef(sdata, chandef);
1672 
1673 	ieee80211_recalc_chanctx_chantype(local, ctx);
1674 
1675 	*changed |= BSS_CHANGED_BANDWIDTH;
1676 	ret = 0;
1677  out:
1678 	mutex_unlock(&local->chanctx_mtx);
1679 	return ret;
1680 }
1681 
1682 void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
1683 {
1684 	WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
1685 
1686 	lockdep_assert_held(&sdata->local->mtx);
1687 
1688 	mutex_lock(&sdata->local->chanctx_mtx);
1689 	__ieee80211_vif_release_channel(sdata);
1690 	mutex_unlock(&sdata->local->chanctx_mtx);
1691 }
1692 
1693 void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
1694 {
1695 	struct ieee80211_local *local = sdata->local;
1696 	struct ieee80211_sub_if_data *ap;
1697 	struct ieee80211_chanctx_conf *conf;
1698 
1699 	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
1700 		return;
1701 
1702 	ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
1703 
1704 	mutex_lock(&local->chanctx_mtx);
1705 
1706 	conf = rcu_dereference_protected(ap->vif.chanctx_conf,
1707 					 lockdep_is_held(&local->chanctx_mtx));
1708 	rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
1709 	mutex_unlock(&local->chanctx_mtx);
1710 }
1711 
1712 void ieee80211_iter_chan_contexts_atomic(
1713 	struct ieee80211_hw *hw,
1714 	void (*iter)(struct ieee80211_hw *hw,
1715 		     struct ieee80211_chanctx_conf *chanctx_conf,
1716 		     void *data),
1717 	void *iter_data)
1718 {
1719 	struct ieee80211_local *local = hw_to_local(hw);
1720 	struct ieee80211_chanctx *ctx;
1721 
1722 	rcu_read_lock();
1723 	list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
1724 		if (ctx->driver_present)
1725 			iter(hw, &ctx->conf, iter_data);
1726 	rcu_read_unlock();
1727 }
1728 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);
1729