xref: /linux/net/mac80211/chan.c (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * mac80211 - channel management
4  * Copyright 2020 - 2025 Intel Corporation
5  */
6 
7 #include <linux/nl80211.h>
8 #include <linux/export.h>
9 #include <linux/rtnetlink.h>
10 #include <net/cfg80211.h>
11 #include "ieee80211_i.h"
12 #include "driver-ops.h"
13 #include "rate.h"
14 
15 static int ieee80211_chanctx_num_assigned(struct ieee80211_local *local,
16 					  struct ieee80211_chanctx *ctx)
17 {
18 	struct ieee80211_link_data *link;
19 	int num = 0;
20 
21 	lockdep_assert_wiphy(local->hw.wiphy);
22 
23 	list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list)
24 		num++;
25 
26 	return num;
27 }
28 
29 static int ieee80211_chanctx_num_reserved(struct ieee80211_local *local,
30 					  struct ieee80211_chanctx *ctx)
31 {
32 	struct ieee80211_link_data *link;
33 	int num = 0;
34 
35 	lockdep_assert_wiphy(local->hw.wiphy);
36 
37 	list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list)
38 		num++;
39 
40 	return num;
41 }
42 
43 int ieee80211_chanctx_refcount(struct ieee80211_local *local,
44 			       struct ieee80211_chanctx *ctx)
45 {
46 	return ieee80211_chanctx_num_assigned(local, ctx) +
47 	       ieee80211_chanctx_num_reserved(local, ctx);
48 }
49 
50 static int ieee80211_num_chanctx(struct ieee80211_local *local, int radio_idx)
51 {
52 	struct ieee80211_chanctx *ctx;
53 	int num = 0;
54 
55 	lockdep_assert_wiphy(local->hw.wiphy);
56 
57 	list_for_each_entry(ctx, &local->chanctx_list, list) {
58 		if (radio_idx >= 0 && ctx->conf.radio_idx != radio_idx)
59 			continue;
60 		num++;
61 	}
62 
63 	return num;
64 }
65 
66 static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local,
67 					     int radio_idx)
68 {
69 	lockdep_assert_wiphy(local->hw.wiphy);
70 
71 	return ieee80211_num_chanctx(local, radio_idx) <
72 	       ieee80211_max_num_channels(local, radio_idx);
73 }
74 
75 static struct ieee80211_chanctx *
76 ieee80211_link_get_chanctx(struct ieee80211_link_data *link)
77 {
78 	struct ieee80211_local *local __maybe_unused = link->sdata->local;
79 	struct ieee80211_chanctx_conf *conf;
80 
81 	conf = rcu_dereference_protected(link->conf->chanctx_conf,
82 					 lockdep_is_held(&local->hw.wiphy->mtx));
83 	if (!conf)
84 		return NULL;
85 
86 	return container_of(conf, struct ieee80211_chanctx, conf);
87 }
88 
89 bool ieee80211_chanreq_identical(const struct ieee80211_chan_req *a,
90 				 const struct ieee80211_chan_req *b)
91 {
92 	if (!cfg80211_chandef_identical(&a->oper, &b->oper))
93 		return false;
94 	if (!a->ap.chan && !b->ap.chan)
95 		return true;
96 	return cfg80211_chandef_identical(&a->ap, &b->ap);
97 }
98 
99 static const struct ieee80211_chan_req *
100 ieee80211_chanreq_compatible(const struct ieee80211_chan_req *a,
101 			     const struct ieee80211_chan_req *b,
102 			     struct ieee80211_chan_req *tmp)
103 {
104 	const struct cfg80211_chan_def *compat;
105 
106 	if (a->ap.chan && b->ap.chan &&
107 	    !cfg80211_chandef_identical(&a->ap, &b->ap))
108 		return NULL;
109 
110 	compat = cfg80211_chandef_compatible(&a->oper, &b->oper);
111 	if (!compat)
112 		return NULL;
113 
114 	/* Note: later code assumes this always fills & returns tmp if compat */
115 	tmp->oper = *compat;
116 	tmp->ap = a->ap.chan ? a->ap : b->ap;
117 	return tmp;
118 }
119 
120 static const struct ieee80211_chan_req *
121 ieee80211_chanctx_compatible(struct ieee80211_chanctx *ctx,
122 			     const struct ieee80211_chan_req *req,
123 			     struct ieee80211_chan_req *tmp)
124 {
125 	const struct ieee80211_chan_req *ret;
126 	struct ieee80211_chan_req tmp2;
127 
128 	*tmp = (struct ieee80211_chan_req){
129 		.oper = ctx->conf.def,
130 		.ap = ctx->conf.ap,
131 	};
132 
133 	ret = ieee80211_chanreq_compatible(tmp, req, &tmp2);
134 	if (!ret)
135 		return NULL;
136 	*tmp = *ret;
137 	return tmp;
138 }
139 
140 static const struct ieee80211_chan_req *
141 ieee80211_chanctx_reserved_chanreq(struct ieee80211_local *local,
142 				   struct ieee80211_chanctx *ctx,
143 				   const struct ieee80211_chan_req *req,
144 				   struct ieee80211_chan_req *tmp)
145 {
146 	struct ieee80211_link_data *link;
147 
148 	lockdep_assert_wiphy(local->hw.wiphy);
149 
150 	if (WARN_ON(!req))
151 		return NULL;
152 
153 	list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list) {
154 		req = ieee80211_chanreq_compatible(&link->reserved, req, tmp);
155 		if (!req)
156 			break;
157 	}
158 
159 	return req;
160 }
161 
162 static const struct ieee80211_chan_req *
163 ieee80211_chanctx_non_reserved_chandef(struct ieee80211_local *local,
164 				       struct ieee80211_chanctx *ctx,
165 				       const struct ieee80211_chan_req *compat,
166 				       struct ieee80211_chan_req *tmp)
167 {
168 	struct ieee80211_link_data *link;
169 	const struct ieee80211_chan_req *comp_def = compat;
170 
171 	lockdep_assert_wiphy(local->hw.wiphy);
172 
173 	list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list) {
174 		struct ieee80211_bss_conf *link_conf = link->conf;
175 
176 		if (link->reserved_chanctx)
177 			continue;
178 
179 		comp_def = ieee80211_chanreq_compatible(&link_conf->chanreq,
180 							comp_def, tmp);
181 		if (!comp_def)
182 			break;
183 	}
184 
185 	return comp_def;
186 }
187 
188 static bool
189 ieee80211_chanctx_can_reserve(struct ieee80211_local *local,
190 			      struct ieee80211_chanctx *ctx,
191 			      const struct ieee80211_chan_req *req)
192 {
193 	struct ieee80211_chan_req tmp;
194 
195 	lockdep_assert_wiphy(local->hw.wiphy);
196 
197 	if (!ieee80211_chanctx_reserved_chanreq(local, ctx, req, &tmp))
198 		return false;
199 
200 	if (!ieee80211_chanctx_non_reserved_chandef(local, ctx, req, &tmp))
201 		return false;
202 
203 	if (!list_empty(&ctx->reserved_links) &&
204 	    ieee80211_chanctx_reserved_chanreq(local, ctx, req, &tmp))
205 		return true;
206 
207 	return false;
208 }
209 
210 static struct ieee80211_chanctx *
211 ieee80211_find_reservation_chanctx(struct ieee80211_local *local,
212 				   const struct ieee80211_chan_req *chanreq,
213 				   enum ieee80211_chanctx_mode mode)
214 {
215 	struct ieee80211_chanctx *ctx;
216 
217 	lockdep_assert_wiphy(local->hw.wiphy);
218 
219 	if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
220 		return NULL;
221 
222 	list_for_each_entry(ctx, &local->chanctx_list, list) {
223 		if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
224 			continue;
225 
226 		if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
227 			continue;
228 
229 		if (!ieee80211_chanctx_can_reserve(local, ctx, chanreq))
230 			continue;
231 
232 		return ctx;
233 	}
234 
235 	return NULL;
236 }
237 
238 static enum nl80211_chan_width ieee80211_get_sta_bw(struct sta_info *sta,
239 						    unsigned int link_id)
240 {
241 	enum ieee80211_sta_rx_bandwidth width;
242 	struct link_sta_info *link_sta;
243 
244 	link_sta = wiphy_dereference(sta->local->hw.wiphy, sta->link[link_id]);
245 
246 	/* no effect if this STA has no presence on this link */
247 	if (!link_sta)
248 		return NL80211_CHAN_WIDTH_20_NOHT;
249 
250 	/*
251 	 * We assume that TX/RX might be asymmetric (so e.g. VHT operating
252 	 * mode notification changes what a STA wants to receive, but not
253 	 * necessarily what it will transmit to us), and therefore use the
254 	 * capabilities here. Calling it RX bandwidth capability is a bit
255 	 * wrong though, since capabilities are in fact symmetric.
256 	 */
257 	width = ieee80211_sta_cap_rx_bw(link_sta);
258 
259 	switch (width) {
260 	case IEEE80211_STA_RX_BW_20:
261 		if (link_sta->pub->ht_cap.ht_supported)
262 			return NL80211_CHAN_WIDTH_20;
263 		else
264 			return NL80211_CHAN_WIDTH_20_NOHT;
265 	case IEEE80211_STA_RX_BW_40:
266 		return NL80211_CHAN_WIDTH_40;
267 	case IEEE80211_STA_RX_BW_80:
268 		return NL80211_CHAN_WIDTH_80;
269 	case IEEE80211_STA_RX_BW_160:
270 		/*
271 		 * This applied for both 160 and 80+80. since we use
272 		 * the returned value to consider degradation of
273 		 * ctx->conf.min_def, we have to make sure to take
274 		 * the bigger one (NL80211_CHAN_WIDTH_160).
275 		 * Otherwise we might try degrading even when not
276 		 * needed, as the max required sta_bw returned (80+80)
277 		 * might be smaller than the configured bw (160).
278 		 */
279 		return NL80211_CHAN_WIDTH_160;
280 	case IEEE80211_STA_RX_BW_320:
281 		return NL80211_CHAN_WIDTH_320;
282 	default:
283 		WARN_ON(1);
284 		return NL80211_CHAN_WIDTH_20;
285 	}
286 }
287 
288 static enum nl80211_chan_width
289 ieee80211_get_max_required_bw(struct ieee80211_link_data *link)
290 {
291 	struct ieee80211_sub_if_data *sdata = link->sdata;
292 	unsigned int link_id = link->link_id;
293 	enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
294 	struct sta_info *sta;
295 
296 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
297 
298 	list_for_each_entry(sta, &sdata->local->sta_list, list) {
299 		if (sdata != sta->sdata &&
300 		    !(sta->sdata->bss && sta->sdata->bss == sdata->bss))
301 			continue;
302 
303 		max_bw = max(max_bw, ieee80211_get_sta_bw(sta, link_id));
304 	}
305 
306 	return max_bw;
307 }
308 
309 static enum nl80211_chan_width
310 ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
311 				      struct ieee80211_chanctx *ctx,
312 				      struct ieee80211_link_data *rsvd_for,
313 				      bool check_reserved)
314 {
315 	struct ieee80211_sub_if_data *sdata;
316 	struct ieee80211_link_data *link;
317 	enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
318 
319 	if (WARN_ON(check_reserved && rsvd_for))
320 		return ctx->conf.def.width;
321 
322 	for_each_sdata_link(local, link) {
323 		enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT;
324 
325 		if (check_reserved) {
326 			if (link->reserved_chanctx != ctx)
327 				continue;
328 		} else if (link != rsvd_for &&
329 			   rcu_access_pointer(link->conf->chanctx_conf) != &ctx->conf)
330 			continue;
331 
332 		switch (link->sdata->vif.type) {
333 		case NL80211_IFTYPE_STATION:
334 			if (!link->sdata->vif.cfg.assoc) {
335 				/*
336 				 * The AP's sta->bandwidth may not yet be set
337 				 * at this point (pre-association), so simply
338 				 * take the width from the chandef. We cannot
339 				 * have TDLS peers yet (only after association).
340 				 */
341 				width = link->conf->chanreq.oper.width;
342 				break;
343 			}
344 			/*
345 			 * otherwise just use min_def like in AP, depending on what
346 			 * we currently think the AP STA (and possibly TDLS peers)
347 			 * require(s)
348 			 */
349 			fallthrough;
350 		case NL80211_IFTYPE_AP:
351 		case NL80211_IFTYPE_AP_VLAN:
352 			width = ieee80211_get_max_required_bw(link);
353 			break;
354 		case NL80211_IFTYPE_P2P_DEVICE:
355 		case NL80211_IFTYPE_NAN:
356 			continue;
357 		case NL80211_IFTYPE_MONITOR:
358 			WARN_ON_ONCE(!ieee80211_hw_check(&local->hw,
359 							 NO_VIRTUAL_MONITOR));
360 			fallthrough;
361 		case NL80211_IFTYPE_ADHOC:
362 		case NL80211_IFTYPE_MESH_POINT:
363 		case NL80211_IFTYPE_OCB:
364 			width = link->conf->chanreq.oper.width;
365 			break;
366 		case NL80211_IFTYPE_WDS:
367 		case NL80211_IFTYPE_UNSPECIFIED:
368 		case NUM_NL80211_IFTYPES:
369 		case NL80211_IFTYPE_P2P_CLIENT:
370 		case NL80211_IFTYPE_P2P_GO:
371 			WARN_ON_ONCE(1);
372 		}
373 
374 		max_bw = max(max_bw, width);
375 	}
376 
377 	/* use the configured bandwidth in case of monitor interface */
378 	sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);
379 	if (sdata &&
380 	    rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == &ctx->conf)
381 		max_bw = max(max_bw, ctx->conf.def.width);
382 
383 	return max_bw;
384 }
385 
386 /*
387  * recalc the min required chan width of the channel context, which is
388  * the max of min required widths of all the interfaces bound to this
389  * channel context.
390  */
391 static u32
392 _ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
393 				  struct ieee80211_chanctx *ctx,
394 				  struct ieee80211_link_data *rsvd_for,
395 				  bool check_reserved)
396 {
397 	enum nl80211_chan_width max_bw;
398 	struct cfg80211_chan_def min_def;
399 
400 	lockdep_assert_wiphy(local->hw.wiphy);
401 
402 	/* don't optimize non-20MHz based and radar_enabled confs */
403 	if (ctx->conf.def.width == NL80211_CHAN_WIDTH_5 ||
404 	    ctx->conf.def.width == NL80211_CHAN_WIDTH_10 ||
405 	    ctx->conf.def.width == NL80211_CHAN_WIDTH_1 ||
406 	    ctx->conf.def.width == NL80211_CHAN_WIDTH_2 ||
407 	    ctx->conf.def.width == NL80211_CHAN_WIDTH_4 ||
408 	    ctx->conf.def.width == NL80211_CHAN_WIDTH_8 ||
409 	    ctx->conf.def.width == NL80211_CHAN_WIDTH_16 ||
410 	    ctx->conf.radar_enabled) {
411 		ctx->conf.min_def = ctx->conf.def;
412 		return 0;
413 	}
414 
415 	max_bw = ieee80211_get_chanctx_max_required_bw(local, ctx, rsvd_for,
416 						       check_reserved);
417 
418 	/* downgrade chandef up to max_bw */
419 	min_def = ctx->conf.def;
420 	while (min_def.width > max_bw)
421 		ieee80211_chandef_downgrade(&min_def, NULL);
422 
423 	if (cfg80211_chandef_identical(&ctx->conf.min_def, &min_def))
424 		return 0;
425 
426 	ctx->conf.min_def = min_def;
427 	if (!ctx->driver_present)
428 		return 0;
429 
430 	return IEEE80211_CHANCTX_CHANGE_MIN_DEF;
431 }
432 
433 static void ieee80211_chan_bw_change(struct ieee80211_local *local,
434 				     struct ieee80211_chanctx *ctx,
435 				     bool reserved, bool narrowed)
436 {
437 	struct sta_info *sta;
438 	struct ieee80211_supported_band *sband =
439 		local->hw.wiphy->bands[ctx->conf.def.chan->band];
440 
441 	rcu_read_lock();
442 	list_for_each_entry_rcu(sta, &local->sta_list,
443 				list) {
444 		struct ieee80211_sub_if_data *sdata = sta->sdata;
445 		enum ieee80211_sta_rx_bandwidth new_sta_bw;
446 		unsigned int link_id;
447 
448 		if (!ieee80211_sdata_running(sta->sdata))
449 			continue;
450 
451 		for (link_id = 0; link_id < ARRAY_SIZE(sta->sdata->link); link_id++) {
452 			struct ieee80211_link_data *link =
453 				rcu_dereference(sdata->link[link_id]);
454 			struct ieee80211_bss_conf *link_conf;
455 			struct cfg80211_chan_def *new_chandef;
456 			struct link_sta_info *link_sta;
457 
458 			if (!link)
459 				continue;
460 
461 			link_conf = link->conf;
462 
463 			if (rcu_access_pointer(link_conf->chanctx_conf) != &ctx->conf)
464 				continue;
465 
466 			link_sta = rcu_dereference(sta->link[link_id]);
467 			if (!link_sta)
468 				continue;
469 
470 			if (reserved)
471 				new_chandef = &link->reserved.oper;
472 			else
473 				new_chandef = &link_conf->chanreq.oper;
474 
475 			new_sta_bw = _ieee80211_sta_cur_vht_bw(link_sta,
476 							       new_chandef);
477 
478 			/* nothing change */
479 			if (new_sta_bw == link_sta->pub->bandwidth)
480 				continue;
481 
482 			/* vif changed to narrow BW and narrow BW for station wasn't
483 			 * requested or vice versa */
484 			if ((new_sta_bw < link_sta->pub->bandwidth) == !narrowed)
485 				continue;
486 
487 			link_sta->pub->bandwidth = new_sta_bw;
488 			rate_control_rate_update(local, sband, link_sta,
489 						 IEEE80211_RC_BW_CHANGED);
490 		}
491 	}
492 	rcu_read_unlock();
493 }
494 
495 /*
496  * recalc the min required chan width of the channel context, which is
497  * the max of min required widths of all the interfaces bound to this
498  * channel context.
499  */
500 void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
501 				      struct ieee80211_chanctx *ctx,
502 				      struct ieee80211_link_data *rsvd_for,
503 				      bool check_reserved)
504 {
505 	u32 changed = _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for,
506 							check_reserved);
507 
508 	if (!changed)
509 		return;
510 
511 	/* check is BW narrowed */
512 	ieee80211_chan_bw_change(local, ctx, false, true);
513 
514 	drv_change_chanctx(local, ctx, changed);
515 
516 	/* check is BW wider */
517 	ieee80211_chan_bw_change(local, ctx, false, false);
518 }
519 
520 static void _ieee80211_change_chanctx(struct ieee80211_local *local,
521 				      struct ieee80211_chanctx *ctx,
522 				      struct ieee80211_chanctx *old_ctx,
523 				      const struct ieee80211_chan_req *chanreq,
524 				      struct ieee80211_link_data *rsvd_for)
525 {
526 	const struct cfg80211_chan_def *chandef = &chanreq->oper;
527 	struct ieee80211_chan_req ctx_req = {
528 		.oper = ctx->conf.def,
529 		.ap = ctx->conf.ap,
530 	};
531 	u32 changed = 0;
532 
533 	/* expected to handle only 20/40/80/160/320 channel widths */
534 	switch (chandef->width) {
535 	case NL80211_CHAN_WIDTH_20_NOHT:
536 	case NL80211_CHAN_WIDTH_20:
537 	case NL80211_CHAN_WIDTH_40:
538 	case NL80211_CHAN_WIDTH_80:
539 	case NL80211_CHAN_WIDTH_80P80:
540 	case NL80211_CHAN_WIDTH_160:
541 	case NL80211_CHAN_WIDTH_320:
542 		break;
543 	default:
544 		WARN_ON(1);
545 	}
546 
547 	/* Check maybe BW narrowed - we do this _before_ calling recalc_chanctx_min_def
548 	 * due to maybe not returning from it, e.g in case new context was added
549 	 * first time with all parameters up to date.
550 	 */
551 	ieee80211_chan_bw_change(local, old_ctx, false, true);
552 
553 	if (ieee80211_chanreq_identical(&ctx_req, chanreq)) {
554 		ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for, false);
555 		return;
556 	}
557 
558 	WARN_ON(ieee80211_chanctx_refcount(local, ctx) > 1 &&
559 		!cfg80211_chandef_compatible(&ctx->conf.def, &chanreq->oper));
560 
561 	ieee80211_remove_wbrf(local, &ctx->conf.def);
562 
563 	if (!cfg80211_chandef_identical(&ctx->conf.def, &chanreq->oper)) {
564 		if (ctx->conf.def.width != chanreq->oper.width)
565 			changed |= IEEE80211_CHANCTX_CHANGE_WIDTH;
566 		if (ctx->conf.def.punctured != chanreq->oper.punctured)
567 			changed |= IEEE80211_CHANCTX_CHANGE_PUNCTURING;
568 	}
569 	if (!cfg80211_chandef_identical(&ctx->conf.ap, &chanreq->ap))
570 		changed |= IEEE80211_CHANCTX_CHANGE_AP;
571 	ctx->conf.def = *chandef;
572 	ctx->conf.ap = chanreq->ap;
573 
574 	/* check if min chanctx also changed */
575 	changed |= _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for, false);
576 
577 	ieee80211_add_wbrf(local, &ctx->conf.def);
578 
579 	drv_change_chanctx(local, ctx, changed);
580 
581 	/* check if BW is wider */
582 	ieee80211_chan_bw_change(local, old_ctx, false, false);
583 }
584 
585 static void ieee80211_change_chanctx(struct ieee80211_local *local,
586 				     struct ieee80211_chanctx *ctx,
587 				     struct ieee80211_chanctx *old_ctx,
588 				     const struct ieee80211_chan_req *chanreq)
589 {
590 	_ieee80211_change_chanctx(local, ctx, old_ctx, chanreq, NULL);
591 }
592 
593 /* Note: if successful, the returned chanctx is reserved for the link */
594 static struct ieee80211_chanctx *
595 ieee80211_find_chanctx(struct ieee80211_local *local,
596 		       struct ieee80211_link_data *link,
597 		       const struct ieee80211_chan_req *chanreq,
598 		       enum ieee80211_chanctx_mode mode)
599 {
600 	struct ieee80211_chan_req tmp;
601 	struct ieee80211_chanctx *ctx;
602 
603 	lockdep_assert_wiphy(local->hw.wiphy);
604 
605 	if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
606 		return NULL;
607 
608 	if (WARN_ON(link->reserved_chanctx))
609 		return NULL;
610 
611 	list_for_each_entry(ctx, &local->chanctx_list, list) {
612 		const struct ieee80211_chan_req *compat;
613 
614 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACE_NONE)
615 			continue;
616 
617 		if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
618 			continue;
619 
620 		compat = ieee80211_chanctx_compatible(ctx, chanreq, &tmp);
621 		if (!compat)
622 			continue;
623 
624 		compat = ieee80211_chanctx_reserved_chanreq(local, ctx,
625 							    compat, &tmp);
626 		if (!compat)
627 			continue;
628 
629 		/*
630 		 * Reserve the chanctx temporarily, as the driver might change
631 		 * active links during callbacks we make into it below and/or
632 		 * later during assignment, which could (otherwise) cause the
633 		 * context to actually be removed.
634 		 */
635 		link->reserved_chanctx = ctx;
636 		list_add(&link->reserved_chanctx_list,
637 			 &ctx->reserved_links);
638 
639 		ieee80211_change_chanctx(local, ctx, ctx, compat);
640 
641 		return ctx;
642 	}
643 
644 	return NULL;
645 }
646 
647 bool ieee80211_is_radar_required(struct ieee80211_local *local,
648 				 struct cfg80211_scan_request *req)
649 {
650 	struct wiphy *wiphy = local->hw.wiphy;
651 	struct ieee80211_link_data *link;
652 	struct ieee80211_channel *chan;
653 	int radio_idx;
654 
655 	lockdep_assert_wiphy(local->hw.wiphy);
656 
657 	if (!req)
658 		return false;
659 
660 	for_each_sdata_link(local, link) {
661 		if (link->radar_required) {
662 			chan = link->conf->chanreq.oper.chan;
663 			radio_idx = cfg80211_get_radio_idx_by_chan(wiphy, chan);
664 
665 			if (ieee80211_is_radio_idx_in_scan_req(wiphy, req,
666 							       radio_idx))
667 				return true;
668 		}
669 	}
670 
671 	return false;
672 }
673 
674 static bool
675 ieee80211_chanctx_radar_required(struct ieee80211_local *local,
676 				 struct ieee80211_chanctx *ctx)
677 {
678 	struct ieee80211_chanctx_conf *conf = &ctx->conf;
679 	struct ieee80211_link_data *link;
680 
681 	lockdep_assert_wiphy(local->hw.wiphy);
682 
683 	for_each_sdata_link(local, link) {
684 		if (rcu_access_pointer(link->conf->chanctx_conf) != conf)
685 			continue;
686 		if (!link->radar_required)
687 			continue;
688 		return true;
689 	}
690 
691 	return false;
692 }
693 
694 static struct ieee80211_chanctx *
695 ieee80211_alloc_chanctx(struct ieee80211_local *local,
696 			const struct ieee80211_chan_req *chanreq,
697 			enum ieee80211_chanctx_mode mode,
698 			int radio_idx)
699 {
700 	struct ieee80211_chanctx *ctx;
701 
702 	lockdep_assert_wiphy(local->hw.wiphy);
703 
704 	ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL);
705 	if (!ctx)
706 		return NULL;
707 
708 	INIT_LIST_HEAD(&ctx->assigned_links);
709 	INIT_LIST_HEAD(&ctx->reserved_links);
710 	ctx->conf.def = chanreq->oper;
711 	ctx->conf.ap = chanreq->ap;
712 	ctx->conf.rx_chains_static = 1;
713 	ctx->conf.rx_chains_dynamic = 1;
714 	ctx->mode = mode;
715 	ctx->conf.radar_enabled = false;
716 	ctx->conf.radio_idx = radio_idx;
717 	ctx->radar_detected = false;
718 	_ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false);
719 
720 	return ctx;
721 }
722 
723 static int ieee80211_add_chanctx(struct ieee80211_local *local,
724 				 struct ieee80211_chanctx *ctx)
725 {
726 	u32 changed;
727 	int err;
728 
729 	lockdep_assert_wiphy(local->hw.wiphy);
730 
731 	ieee80211_add_wbrf(local, &ctx->conf.def);
732 
733 	/* turn idle off *before* setting channel -- some drivers need that */
734 	changed = ieee80211_idle_off(local);
735 	if (changed)
736 		ieee80211_hw_config(local, -1, changed);
737 
738 	err = drv_add_chanctx(local, ctx);
739 	if (err) {
740 		ieee80211_recalc_idle(local);
741 		return err;
742 	}
743 
744 	return 0;
745 }
746 
747 static struct ieee80211_chanctx *
748 ieee80211_new_chanctx(struct ieee80211_local *local,
749 		      const struct ieee80211_chan_req *chanreq,
750 		      enum ieee80211_chanctx_mode mode,
751 		      bool assign_on_failure,
752 		      int radio_idx)
753 {
754 	struct ieee80211_chanctx *ctx;
755 	int err;
756 
757 	lockdep_assert_wiphy(local->hw.wiphy);
758 
759 	ctx = ieee80211_alloc_chanctx(local, chanreq, mode, radio_idx);
760 	if (!ctx)
761 		return ERR_PTR(-ENOMEM);
762 
763 	err = ieee80211_add_chanctx(local, ctx);
764 	if (!assign_on_failure && err) {
765 		kfree(ctx);
766 		return ERR_PTR(err);
767 	}
768 	/* We ignored a driver error, see _ieee80211_set_active_links */
769 	WARN_ON_ONCE(err && !local->in_reconfig);
770 
771 	list_add_rcu(&ctx->list, &local->chanctx_list);
772 	return ctx;
773 }
774 
775 static void ieee80211_del_chanctx(struct ieee80211_local *local,
776 				  struct ieee80211_chanctx *ctx,
777 				  bool skip_idle_recalc)
778 {
779 	lockdep_assert_wiphy(local->hw.wiphy);
780 
781 	drv_remove_chanctx(local, ctx);
782 
783 	if (!skip_idle_recalc)
784 		ieee80211_recalc_idle(local);
785 
786 	ieee80211_remove_wbrf(local, &ctx->conf.def);
787 }
788 
789 static void ieee80211_free_chanctx(struct ieee80211_local *local,
790 				   struct ieee80211_chanctx *ctx,
791 				   bool skip_idle_recalc)
792 {
793 	lockdep_assert_wiphy(local->hw.wiphy);
794 
795 	WARN_ON_ONCE(ieee80211_chanctx_refcount(local, ctx) != 0);
796 
797 	list_del_rcu(&ctx->list);
798 	ieee80211_del_chanctx(local, ctx, skip_idle_recalc);
799 	kfree_rcu(ctx, rcu_head);
800 }
801 
802 void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
803 				       struct ieee80211_chanctx *ctx)
804 {
805 	struct ieee80211_chanctx_conf *conf = &ctx->conf;
806 	const struct ieee80211_chan_req *compat = NULL;
807 	struct ieee80211_link_data *link;
808 	struct ieee80211_chan_req tmp;
809 	struct sta_info *sta;
810 
811 	lockdep_assert_wiphy(local->hw.wiphy);
812 
813 	for_each_sdata_link(local, link) {
814 		struct ieee80211_bss_conf *link_conf;
815 
816 		if (link->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
817 			continue;
818 
819 		link_conf = link->conf;
820 
821 		if (rcu_access_pointer(link_conf->chanctx_conf) != conf)
822 			continue;
823 
824 		if (!compat)
825 			compat = &link_conf->chanreq;
826 
827 		compat = ieee80211_chanreq_compatible(&link_conf->chanreq,
828 						      compat, &tmp);
829 		if (WARN_ON_ONCE(!compat))
830 			return;
831 	}
832 
833 	if (WARN_ON_ONCE(!compat))
834 		return;
835 
836 	/* TDLS peers can sometimes affect the chandef width */
837 	list_for_each_entry(sta, &local->sta_list, list) {
838 		struct ieee80211_sub_if_data *sdata = sta->sdata;
839 		struct ieee80211_chan_req tdls_chanreq = {};
840 		int tdls_link_id;
841 
842 		if (!sta->uploaded ||
843 		    !test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW) ||
844 		    !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
845 		    !sta->tdls_chandef.chan)
846 			continue;
847 
848 		tdls_link_id = ieee80211_tdls_sta_link_id(sta);
849 		link = sdata_dereference(sdata->link[tdls_link_id], sdata);
850 		if (!link)
851 			continue;
852 
853 		if (rcu_access_pointer(link->conf->chanctx_conf) != conf)
854 			continue;
855 
856 		tdls_chanreq.oper = sta->tdls_chandef;
857 
858 		/* note this always fills and returns &tmp if compat */
859 		compat = ieee80211_chanreq_compatible(&tdls_chanreq,
860 						      compat, &tmp);
861 		if (WARN_ON_ONCE(!compat))
862 			return;
863 	}
864 
865 	ieee80211_change_chanctx(local, ctx, ctx, compat);
866 }
867 
868 static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
869 					   struct ieee80211_chanctx *chanctx)
870 {
871 	bool radar_enabled;
872 
873 	lockdep_assert_wiphy(local->hw.wiphy);
874 
875 	radar_enabled = ieee80211_chanctx_radar_required(local, chanctx);
876 
877 	if (radar_enabled == chanctx->conf.radar_enabled)
878 		return;
879 
880 	chanctx->conf.radar_enabled = radar_enabled;
881 
882 	drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
883 }
884 
885 static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
886 					 struct ieee80211_chanctx *new_ctx,
887 					 bool assign_on_failure)
888 {
889 	struct ieee80211_sub_if_data *sdata = link->sdata;
890 	struct ieee80211_local *local = sdata->local;
891 	struct ieee80211_chanctx_conf *conf;
892 	struct ieee80211_chanctx *curr_ctx = NULL;
893 	bool new_idle;
894 	int ret;
895 
896 	if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN))
897 		return -EOPNOTSUPP;
898 
899 	conf = rcu_dereference_protected(link->conf->chanctx_conf,
900 					 lockdep_is_held(&local->hw.wiphy->mtx));
901 
902 	if (conf && !local->in_reconfig) {
903 		curr_ctx = container_of(conf, struct ieee80211_chanctx, conf);
904 
905 		drv_unassign_vif_chanctx(local, sdata, link->conf, curr_ctx);
906 		conf = NULL;
907 		list_del(&link->assigned_chanctx_list);
908 	}
909 
910 	if (new_ctx) {
911 		/* recalc considering the link we'll use it for now */
912 		ieee80211_recalc_chanctx_min_def(local, new_ctx, link, false);
913 
914 		ret = drv_assign_vif_chanctx(local, sdata, link->conf, new_ctx);
915 		if (assign_on_failure || !ret) {
916 			/* Need to continue, see _ieee80211_set_active_links */
917 			WARN_ON_ONCE(ret && !local->in_reconfig);
918 			ret = 0;
919 
920 			/* succeeded, so commit it to the data structures */
921 			conf = &new_ctx->conf;
922 			if (!local->in_reconfig)
923 				list_add(&link->assigned_chanctx_list,
924 					 &new_ctx->assigned_links);
925 		}
926 	} else {
927 		ret = 0;
928 	}
929 
930 	rcu_assign_pointer(link->conf->chanctx_conf, conf);
931 
932 	if (curr_ctx && ieee80211_chanctx_num_assigned(local, curr_ctx) > 0) {
933 		ieee80211_recalc_chanctx_chantype(local, curr_ctx);
934 		ieee80211_recalc_smps_chanctx(local, curr_ctx);
935 		ieee80211_recalc_radar_chanctx(local, curr_ctx);
936 		ieee80211_recalc_chanctx_min_def(local, curr_ctx, NULL, false);
937 	}
938 
939 	if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) {
940 		ieee80211_recalc_txpower(link, false);
941 		ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL, false);
942 	}
943 
944 	if (conf) {
945 		new_idle = false;
946 	} else {
947 		struct ieee80211_link_data *tmp;
948 
949 		new_idle = true;
950 		for_each_sdata_link(local, tmp) {
951 			if (rcu_access_pointer(tmp->conf->chanctx_conf)) {
952 				new_idle = false;
953 				break;
954 			}
955 		}
956 	}
957 
958 	if (new_idle != sdata->vif.cfg.idle) {
959 		sdata->vif.cfg.idle = new_idle;
960 
961 		if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
962 		    sdata->vif.type != NL80211_IFTYPE_MONITOR)
963 			ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE);
964 	}
965 
966 	ieee80211_check_fast_xmit_iface(sdata);
967 
968 	return ret;
969 }
970 
971 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
972 				   struct ieee80211_chanctx *chanctx)
973 {
974 	struct ieee80211_sub_if_data *sdata;
975 	u8 rx_chains_static, rx_chains_dynamic;
976 	struct ieee80211_link_data *link;
977 
978 	lockdep_assert_wiphy(local->hw.wiphy);
979 
980 	rx_chains_static = 1;
981 	rx_chains_dynamic = 1;
982 
983 	for_each_sdata_link(local, link) {
984 		u8 needed_static, needed_dynamic;
985 
986 		switch (link->sdata->vif.type) {
987 		case NL80211_IFTYPE_STATION:
988 			if (!link->sdata->u.mgd.associated)
989 				continue;
990 			break;
991 		case NL80211_IFTYPE_MONITOR:
992 			if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
993 				continue;
994 			break;
995 		case NL80211_IFTYPE_AP:
996 		case NL80211_IFTYPE_ADHOC:
997 		case NL80211_IFTYPE_MESH_POINT:
998 		case NL80211_IFTYPE_OCB:
999 			break;
1000 		default:
1001 			continue;
1002 		}
1003 
1004 		if (rcu_access_pointer(link->conf->chanctx_conf) != &chanctx->conf)
1005 			continue;
1006 
1007 		if (link->sdata->vif.type == NL80211_IFTYPE_MONITOR) {
1008 			rx_chains_dynamic = rx_chains_static = local->rx_chains;
1009 			break;
1010 		}
1011 
1012 		switch (link->smps_mode) {
1013 		default:
1014 			WARN_ONCE(1, "Invalid SMPS mode %d\n",
1015 				  link->smps_mode);
1016 			fallthrough;
1017 		case IEEE80211_SMPS_OFF:
1018 			needed_static = link->needed_rx_chains;
1019 			needed_dynamic = link->needed_rx_chains;
1020 			break;
1021 		case IEEE80211_SMPS_DYNAMIC:
1022 			needed_static = 1;
1023 			needed_dynamic = link->needed_rx_chains;
1024 			break;
1025 		case IEEE80211_SMPS_STATIC:
1026 			needed_static = 1;
1027 			needed_dynamic = 1;
1028 			break;
1029 		}
1030 
1031 		rx_chains_static = max(rx_chains_static, needed_static);
1032 		rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
1033 	}
1034 
1035 	/* Disable SMPS for the monitor interface */
1036 	sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);
1037 	if (sdata &&
1038 	    rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == &chanctx->conf)
1039 		rx_chains_dynamic = rx_chains_static = local->rx_chains;
1040 
1041 	if (rx_chains_static == chanctx->conf.rx_chains_static &&
1042 	    rx_chains_dynamic == chanctx->conf.rx_chains_dynamic)
1043 		return;
1044 
1045 	chanctx->conf.rx_chains_static = rx_chains_static;
1046 	chanctx->conf.rx_chains_dynamic = rx_chains_dynamic;
1047 	drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
1048 }
1049 
1050 static void
1051 __ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
1052 				       bool clear)
1053 {
1054 	struct ieee80211_sub_if_data *sdata = link->sdata;
1055 	unsigned int link_id = link->link_id;
1056 	struct ieee80211_bss_conf *link_conf = link->conf;
1057 	struct ieee80211_local *local __maybe_unused = sdata->local;
1058 	struct ieee80211_sub_if_data *vlan;
1059 	struct ieee80211_chanctx_conf *conf;
1060 
1061 	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
1062 		return;
1063 
1064 	lockdep_assert_wiphy(local->hw.wiphy);
1065 
1066 	/* Check that conf exists, even when clearing this function
1067 	 * must be called with the AP's channel context still there
1068 	 * as it would otherwise cause VLANs to have an invalid
1069 	 * channel context pointer for a while, possibly pointing
1070 	 * to a channel context that has already been freed.
1071 	 */
1072 	conf = rcu_dereference_protected(link_conf->chanctx_conf,
1073 					 lockdep_is_held(&local->hw.wiphy->mtx));
1074 	WARN_ON(!conf);
1075 
1076 	if (clear)
1077 		conf = NULL;
1078 
1079 	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
1080 		struct ieee80211_bss_conf *vlan_conf;
1081 
1082 		vlan_conf = wiphy_dereference(local->hw.wiphy,
1083 					      vlan->vif.link_conf[link_id]);
1084 		if (WARN_ON(!vlan_conf))
1085 			continue;
1086 
1087 		rcu_assign_pointer(vlan_conf->chanctx_conf, conf);
1088 	}
1089 }
1090 
1091 void ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
1092 					  bool clear)
1093 {
1094 	struct ieee80211_local *local = link->sdata->local;
1095 
1096 	lockdep_assert_wiphy(local->hw.wiphy);
1097 
1098 	__ieee80211_link_copy_chanctx_to_vlans(link, clear);
1099 }
1100 
1101 void ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link)
1102 {
1103 	struct ieee80211_sub_if_data *sdata = link->sdata;
1104 	struct ieee80211_chanctx *ctx = link->reserved_chanctx;
1105 
1106 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
1107 
1108 	if (WARN_ON(!ctx))
1109 		return;
1110 
1111 	list_del(&link->reserved_chanctx_list);
1112 	link->reserved_chanctx = NULL;
1113 
1114 	if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0) {
1115 		if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
1116 			if (WARN_ON(!ctx->replace_ctx))
1117 				return;
1118 
1119 			WARN_ON(ctx->replace_ctx->replace_state !=
1120 			        IEEE80211_CHANCTX_WILL_BE_REPLACED);
1121 			WARN_ON(ctx->replace_ctx->replace_ctx != ctx);
1122 
1123 			ctx->replace_ctx->replace_ctx = NULL;
1124 			ctx->replace_ctx->replace_state =
1125 					IEEE80211_CHANCTX_REPLACE_NONE;
1126 
1127 			list_del_rcu(&ctx->list);
1128 			kfree_rcu(ctx, rcu_head);
1129 		} else {
1130 			ieee80211_free_chanctx(sdata->local, ctx, false);
1131 		}
1132 	}
1133 }
1134 
1135 static struct ieee80211_chanctx *
1136 ieee80211_replace_chanctx(struct ieee80211_local *local,
1137 			  const struct ieee80211_chan_req *chanreq,
1138 			  enum ieee80211_chanctx_mode mode,
1139 			  struct ieee80211_chanctx *curr_ctx)
1140 {
1141 	struct ieee80211_chanctx *new_ctx, *ctx;
1142 	struct wiphy *wiphy = local->hw.wiphy;
1143 	const struct wiphy_radio *radio;
1144 
1145 	if (!curr_ctx || (curr_ctx->replace_state ==
1146 			  IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
1147 	    !list_empty(&curr_ctx->reserved_links)) {
1148 		/*
1149 		 * Another link already requested this context for a
1150 		 * reservation. Find another one hoping all links assigned
1151 		 * to it will also switch soon enough.
1152 		 *
1153 		 * TODO: This needs a little more work as some cases
1154 		 * (more than 2 chanctx capable devices) may fail which could
1155 		 * otherwise succeed provided some channel context juggling was
1156 		 * performed.
1157 		 *
1158 		 * Consider ctx1..3, link1..6, each ctx has 2 links. link1 and
1159 		 * link2 from ctx1 request new different chandefs starting 2
1160 		 * in-place reservations with ctx4 and ctx5 replacing ctx1 and
1161 		 * ctx2 respectively. Next link5 and link6 from ctx3 reserve
1162 		 * ctx4. If link3 and link4 remain on ctx2 as they are then this
1163 		 * fails unless `replace_ctx` from ctx5 is replaced with ctx3.
1164 		 */
1165 		list_for_each_entry(ctx, &local->chanctx_list, list) {
1166 			if (ctx->replace_state !=
1167 			    IEEE80211_CHANCTX_REPLACE_NONE)
1168 				continue;
1169 
1170 			if (!list_empty(&ctx->reserved_links))
1171 				continue;
1172 
1173 			if (ctx->conf.radio_idx >= 0) {
1174 				radio = &wiphy->radio[ctx->conf.radio_idx];
1175 				if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper))
1176 					continue;
1177 			}
1178 
1179 			curr_ctx = ctx;
1180 			break;
1181 		}
1182 	}
1183 
1184 	/*
1185 	 * If that's true then all available contexts already have reservations
1186 	 * and cannot be used.
1187 	 */
1188 	if (!curr_ctx || (curr_ctx->replace_state ==
1189 			  IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
1190 	    !list_empty(&curr_ctx->reserved_links))
1191 		return ERR_PTR(-EBUSY);
1192 
1193 	new_ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1);
1194 	if (!new_ctx)
1195 		return ERR_PTR(-ENOMEM);
1196 
1197 	new_ctx->replace_ctx = curr_ctx;
1198 	new_ctx->replace_state = IEEE80211_CHANCTX_REPLACES_OTHER;
1199 
1200 	curr_ctx->replace_ctx = new_ctx;
1201 	curr_ctx->replace_state = IEEE80211_CHANCTX_WILL_BE_REPLACED;
1202 
1203 	list_add_rcu(&new_ctx->list, &local->chanctx_list);
1204 
1205 	return new_ctx;
1206 }
1207 
1208 static bool
1209 ieee80211_find_available_radio(struct ieee80211_local *local,
1210 			       const struct ieee80211_chan_req *chanreq,
1211 			       u32 radio_mask, int *radio_idx)
1212 {
1213 	struct wiphy *wiphy = local->hw.wiphy;
1214 	const struct wiphy_radio *radio;
1215 	int i;
1216 
1217 	*radio_idx = -1;
1218 	if (!wiphy->n_radio)
1219 		return true;
1220 
1221 	for (i = 0; i < wiphy->n_radio; i++) {
1222 		if (!(radio_mask & BIT(i)))
1223 			continue;
1224 
1225 		radio = &wiphy->radio[i];
1226 		if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper))
1227 			continue;
1228 
1229 		if (!ieee80211_can_create_new_chanctx(local, i))
1230 			continue;
1231 
1232 		*radio_idx = i;
1233 		return true;
1234 	}
1235 
1236 	return false;
1237 }
1238 
1239 int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link,
1240 				   const struct ieee80211_chan_req *chanreq,
1241 				   enum ieee80211_chanctx_mode mode,
1242 				   bool radar_required)
1243 {
1244 	struct ieee80211_sub_if_data *sdata = link->sdata;
1245 	struct ieee80211_local *local = sdata->local;
1246 	struct ieee80211_chanctx *new_ctx, *curr_ctx;
1247 	int radio_idx;
1248 
1249 	lockdep_assert_wiphy(local->hw.wiphy);
1250 
1251 	curr_ctx = ieee80211_link_get_chanctx(link);
1252 	if (curr_ctx && !local->ops->switch_vif_chanctx)
1253 		return -EOPNOTSUPP;
1254 
1255 	new_ctx = ieee80211_find_reservation_chanctx(local, chanreq, mode);
1256 	if (!new_ctx) {
1257 		if (ieee80211_can_create_new_chanctx(local, -1) &&
1258 		    ieee80211_find_available_radio(local, chanreq,
1259 						   sdata->wdev.radio_mask,
1260 						   &radio_idx))
1261 			new_ctx = ieee80211_new_chanctx(local, chanreq, mode,
1262 							false, radio_idx);
1263 		else
1264 			new_ctx = ieee80211_replace_chanctx(local, chanreq,
1265 							    mode, curr_ctx);
1266 		if (IS_ERR(new_ctx))
1267 			return PTR_ERR(new_ctx);
1268 	}
1269 
1270 	list_add(&link->reserved_chanctx_list, &new_ctx->reserved_links);
1271 	link->reserved_chanctx = new_ctx;
1272 	link->reserved = *chanreq;
1273 	link->reserved_radar_required = radar_required;
1274 	link->reserved_ready = false;
1275 
1276 	return 0;
1277 }
1278 
1279 static void
1280 ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link)
1281 {
1282 	struct ieee80211_sub_if_data *sdata = link->sdata;
1283 
1284 	switch (sdata->vif.type) {
1285 	case NL80211_IFTYPE_ADHOC:
1286 	case NL80211_IFTYPE_AP:
1287 	case NL80211_IFTYPE_MESH_POINT:
1288 	case NL80211_IFTYPE_OCB:
1289 		wiphy_work_queue(sdata->local->hw.wiphy,
1290 				 &link->csa.finalize_work);
1291 		break;
1292 	case NL80211_IFTYPE_STATION:
1293 		wiphy_delayed_work_queue(sdata->local->hw.wiphy,
1294 					 &link->u.mgd.csa.switch_work, 0);
1295 		break;
1296 	case NL80211_IFTYPE_UNSPECIFIED:
1297 	case NL80211_IFTYPE_AP_VLAN:
1298 	case NL80211_IFTYPE_WDS:
1299 	case NL80211_IFTYPE_MONITOR:
1300 	case NL80211_IFTYPE_P2P_CLIENT:
1301 	case NL80211_IFTYPE_P2P_GO:
1302 	case NL80211_IFTYPE_P2P_DEVICE:
1303 	case NL80211_IFTYPE_NAN:
1304 	case NUM_NL80211_IFTYPES:
1305 		WARN_ON(1);
1306 		break;
1307 	}
1308 }
1309 
1310 static void
1311 ieee80211_link_update_chanreq(struct ieee80211_link_data *link,
1312 			      const struct ieee80211_chan_req *chanreq)
1313 {
1314 	struct ieee80211_sub_if_data *sdata = link->sdata;
1315 	unsigned int link_id = link->link_id;
1316 	struct ieee80211_sub_if_data *vlan;
1317 
1318 	link->conf->chanreq = *chanreq;
1319 
1320 	if (sdata->vif.type != NL80211_IFTYPE_AP)
1321 		return;
1322 
1323 	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
1324 		struct ieee80211_bss_conf *vlan_conf;
1325 
1326 		vlan_conf = wiphy_dereference(sdata->local->hw.wiphy,
1327 					      vlan->vif.link_conf[link_id]);
1328 		if (WARN_ON(!vlan_conf))
1329 			continue;
1330 
1331 		vlan_conf->chanreq = *chanreq;
1332 	}
1333 }
1334 
1335 static int
1336 ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)
1337 {
1338 	struct ieee80211_sub_if_data *sdata = link->sdata;
1339 	struct ieee80211_bss_conf *link_conf = link->conf;
1340 	struct ieee80211_local *local = sdata->local;
1341 	struct ieee80211_vif_chanctx_switch vif_chsw[1] = {};
1342 	struct ieee80211_chanctx *old_ctx, *new_ctx;
1343 	const struct ieee80211_chan_req *chanreq;
1344 	struct ieee80211_chan_req tmp;
1345 	u64 changed = 0;
1346 	int err;
1347 
1348 	lockdep_assert_wiphy(local->hw.wiphy);
1349 
1350 	new_ctx = link->reserved_chanctx;
1351 	old_ctx = ieee80211_link_get_chanctx(link);
1352 
1353 	if (WARN_ON(!link->reserved_ready))
1354 		return -EBUSY;
1355 
1356 	if (WARN_ON(!new_ctx))
1357 		return -EINVAL;
1358 
1359 	if (WARN_ON(!old_ctx))
1360 		return -EINVAL;
1361 
1362 	if (WARN_ON(new_ctx->replace_state ==
1363 		    IEEE80211_CHANCTX_REPLACES_OTHER))
1364 		return -EINVAL;
1365 
1366 	chanreq = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
1367 							 &link->reserved,
1368 							 &tmp);
1369 	if (WARN_ON(!chanreq))
1370 		return -EINVAL;
1371 
1372 	if (link_conf->chanreq.oper.width != link->reserved.oper.width)
1373 		changed = BSS_CHANGED_BANDWIDTH;
1374 
1375 	ieee80211_link_update_chanreq(link, &link->reserved);
1376 
1377 	_ieee80211_change_chanctx(local, new_ctx, old_ctx, chanreq, link);
1378 
1379 	vif_chsw[0].vif = &sdata->vif;
1380 	vif_chsw[0].old_ctx = &old_ctx->conf;
1381 	vif_chsw[0].new_ctx = &new_ctx->conf;
1382 	vif_chsw[0].link_conf = link->conf;
1383 
1384 	list_del(&link->reserved_chanctx_list);
1385 	link->reserved_chanctx = NULL;
1386 
1387 	err = drv_switch_vif_chanctx(local, vif_chsw, 1,
1388 				     CHANCTX_SWMODE_REASSIGN_VIF);
1389 	if (err) {
1390 		if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
1391 			ieee80211_free_chanctx(local, new_ctx, false);
1392 
1393 		goto out;
1394 	}
1395 
1396 	link->radar_required = link->reserved_radar_required;
1397 	list_move(&link->assigned_chanctx_list, &new_ctx->assigned_links);
1398 	rcu_assign_pointer(link_conf->chanctx_conf, &new_ctx->conf);
1399 
1400 	if (sdata->vif.type == NL80211_IFTYPE_AP)
1401 		__ieee80211_link_copy_chanctx_to_vlans(link, false);
1402 
1403 	ieee80211_check_fast_xmit_iface(sdata);
1404 
1405 	if (ieee80211_chanctx_refcount(local, old_ctx) == 0)
1406 		ieee80211_free_chanctx(local, old_ctx, false);
1407 
1408 	ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL, false);
1409 	ieee80211_recalc_smps_chanctx(local, new_ctx);
1410 	ieee80211_recalc_radar_chanctx(local, new_ctx);
1411 
1412 	if (changed)
1413 		ieee80211_link_info_change_notify(sdata, link, changed);
1414 
1415 out:
1416 	ieee80211_link_chanctx_reservation_complete(link);
1417 	return err;
1418 }
1419 
1420 static int
1421 ieee80211_link_use_reserved_assign(struct ieee80211_link_data *link)
1422 {
1423 	struct ieee80211_sub_if_data *sdata = link->sdata;
1424 	struct ieee80211_local *local = sdata->local;
1425 	struct ieee80211_chanctx *old_ctx, *new_ctx;
1426 	const struct ieee80211_chan_req *chanreq;
1427 	struct ieee80211_chan_req tmp;
1428 	int err;
1429 
1430 	old_ctx = ieee80211_link_get_chanctx(link);
1431 	new_ctx = link->reserved_chanctx;
1432 
1433 	if (WARN_ON(!link->reserved_ready))
1434 		return -EINVAL;
1435 
1436 	if (WARN_ON(old_ctx))
1437 		return -EINVAL;
1438 
1439 	if (WARN_ON(!new_ctx))
1440 		return -EINVAL;
1441 
1442 	if (WARN_ON(new_ctx->replace_state ==
1443 		    IEEE80211_CHANCTX_REPLACES_OTHER))
1444 		return -EINVAL;
1445 
1446 	chanreq = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
1447 							 &link->reserved,
1448 							 &tmp);
1449 	if (WARN_ON(!chanreq))
1450 		return -EINVAL;
1451 
1452 	ieee80211_change_chanctx(local, new_ctx, new_ctx, chanreq);
1453 
1454 	list_del(&link->reserved_chanctx_list);
1455 	link->reserved_chanctx = NULL;
1456 
1457 	err = ieee80211_assign_link_chanctx(link, new_ctx, false);
1458 	if (err) {
1459 		if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
1460 			ieee80211_free_chanctx(local, new_ctx, false);
1461 
1462 		goto out;
1463 	}
1464 
1465 out:
1466 	ieee80211_link_chanctx_reservation_complete(link);
1467 	return err;
1468 }
1469 
1470 static bool
1471 ieee80211_link_has_in_place_reservation(struct ieee80211_link_data *link)
1472 {
1473 	struct ieee80211_sub_if_data *sdata = link->sdata;
1474 	struct ieee80211_chanctx *old_ctx, *new_ctx;
1475 
1476 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
1477 
1478 	new_ctx = link->reserved_chanctx;
1479 	old_ctx = ieee80211_link_get_chanctx(link);
1480 
1481 	if (!old_ctx)
1482 		return false;
1483 
1484 	if (WARN_ON(!new_ctx))
1485 		return false;
1486 
1487 	if (old_ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
1488 		return false;
1489 
1490 	if (new_ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1491 		return false;
1492 
1493 	return true;
1494 }
1495 
1496 static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local,
1497 				      int n_vifs)
1498 {
1499 	struct ieee80211_vif_chanctx_switch *vif_chsw;
1500 	struct ieee80211_link_data *link;
1501 	struct ieee80211_chanctx *ctx, *old_ctx;
1502 	int i, err;
1503 
1504 	lockdep_assert_wiphy(local->hw.wiphy);
1505 
1506 	vif_chsw = kcalloc(n_vifs, sizeof(vif_chsw[0]), GFP_KERNEL);
1507 	if (!vif_chsw)
1508 		return -ENOMEM;
1509 
1510 	i = 0;
1511 	list_for_each_entry(ctx, &local->chanctx_list, list) {
1512 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1513 			continue;
1514 
1515 		if (WARN_ON(!ctx->replace_ctx)) {
1516 			err = -EINVAL;
1517 			goto out;
1518 		}
1519 
1520 		list_for_each_entry(link, &ctx->reserved_links,
1521 				    reserved_chanctx_list) {
1522 			if (!ieee80211_link_has_in_place_reservation(link))
1523 				continue;
1524 
1525 			old_ctx = ieee80211_link_get_chanctx(link);
1526 			vif_chsw[i].vif = &link->sdata->vif;
1527 			vif_chsw[i].old_ctx = &old_ctx->conf;
1528 			vif_chsw[i].new_ctx = &ctx->conf;
1529 			vif_chsw[i].link_conf = link->conf;
1530 
1531 			i++;
1532 		}
1533 	}
1534 
1535 	err = drv_switch_vif_chanctx(local, vif_chsw, n_vifs,
1536 				     CHANCTX_SWMODE_SWAP_CONTEXTS);
1537 
1538 out:
1539 	kfree(vif_chsw);
1540 	return err;
1541 }
1542 
1543 static int ieee80211_chsw_switch_ctxs(struct ieee80211_local *local)
1544 {
1545 	struct ieee80211_chanctx *ctx;
1546 	int err;
1547 
1548 	lockdep_assert_wiphy(local->hw.wiphy);
1549 
1550 	list_for_each_entry(ctx, &local->chanctx_list, list) {
1551 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1552 			continue;
1553 
1554 		if (!list_empty(&ctx->replace_ctx->assigned_links))
1555 			continue;
1556 
1557 		ieee80211_del_chanctx(local, ctx->replace_ctx, false);
1558 		err = ieee80211_add_chanctx(local, ctx);
1559 		if (err)
1560 			goto err;
1561 	}
1562 
1563 	return 0;
1564 
1565 err:
1566 	WARN_ON(ieee80211_add_chanctx(local, ctx));
1567 	list_for_each_entry_continue_reverse(ctx, &local->chanctx_list, list) {
1568 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1569 			continue;
1570 
1571 		if (!list_empty(&ctx->replace_ctx->assigned_links))
1572 			continue;
1573 
1574 		ieee80211_del_chanctx(local, ctx, false);
1575 		WARN_ON(ieee80211_add_chanctx(local, ctx->replace_ctx));
1576 	}
1577 
1578 	return err;
1579 }
1580 
1581 static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
1582 {
1583 	struct ieee80211_chanctx *ctx, *ctx_tmp, *old_ctx;
1584 	int err, n_assigned, n_reserved, n_ready;
1585 	int n_ctx = 0, n_vifs_switch = 0, n_vifs_assign = 0, n_vifs_ctxless = 0;
1586 
1587 	lockdep_assert_wiphy(local->hw.wiphy);
1588 
1589 	/*
1590 	 * If there are 2 independent pairs of channel contexts performing
1591 	 * cross-switch of their vifs this code will still wait until both are
1592 	 * ready even though it could be possible to switch one before the
1593 	 * other is ready.
1594 	 *
1595 	 * For practical reasons and code simplicity just do a single huge
1596 	 * switch.
1597 	 */
1598 
1599 	/*
1600 	 * Verify if the reservation is still feasible.
1601 	 *  - if it's not then disconnect
1602 	 *  - if it is but not all vifs necessary are ready then defer
1603 	 */
1604 
1605 	list_for_each_entry(ctx, &local->chanctx_list, list) {
1606 		struct ieee80211_link_data *link;
1607 
1608 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1609 			continue;
1610 
1611 		if (WARN_ON(!ctx->replace_ctx)) {
1612 			err = -EINVAL;
1613 			goto err;
1614 		}
1615 
1616 		n_ctx++;
1617 
1618 		n_assigned = 0;
1619 		n_reserved = 0;
1620 		n_ready = 0;
1621 
1622 		list_for_each_entry(link, &ctx->replace_ctx->assigned_links,
1623 				    assigned_chanctx_list) {
1624 			n_assigned++;
1625 			if (link->reserved_chanctx) {
1626 				n_reserved++;
1627 				if (link->reserved_ready)
1628 					n_ready++;
1629 			}
1630 		}
1631 
1632 		if (n_assigned != n_reserved) {
1633 			if (n_ready == n_reserved) {
1634 				wiphy_info(local->hw.wiphy,
1635 					   "channel context reservation cannot be finalized because some interfaces aren't switching\n");
1636 				err = -EBUSY;
1637 				goto err;
1638 			}
1639 
1640 			return -EAGAIN;
1641 		}
1642 
1643 		ctx->conf.radar_enabled = false;
1644 		list_for_each_entry(link, &ctx->reserved_links,
1645 				    reserved_chanctx_list) {
1646 			if (ieee80211_link_has_in_place_reservation(link) &&
1647 			    !link->reserved_ready)
1648 				return -EAGAIN;
1649 
1650 			old_ctx = ieee80211_link_get_chanctx(link);
1651 			if (old_ctx) {
1652 				if (old_ctx->replace_state ==
1653 				    IEEE80211_CHANCTX_WILL_BE_REPLACED)
1654 					n_vifs_switch++;
1655 				else
1656 					n_vifs_assign++;
1657 			} else {
1658 				n_vifs_ctxless++;
1659 			}
1660 
1661 			if (link->reserved_radar_required)
1662 				ctx->conf.radar_enabled = true;
1663 		}
1664 	}
1665 
1666 	if (WARN_ON(n_ctx == 0) ||
1667 	    WARN_ON(n_vifs_switch == 0 &&
1668 		    n_vifs_assign == 0 &&
1669 		    n_vifs_ctxless == 0)) {
1670 		err = -EINVAL;
1671 		goto err;
1672 	}
1673 
1674 	/* update station rate control and min width before switch */
1675 	list_for_each_entry(ctx, &local->chanctx_list, list) {
1676 		struct ieee80211_link_data *link;
1677 
1678 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1679 			continue;
1680 
1681 		if (WARN_ON(!ctx->replace_ctx)) {
1682 			err = -EINVAL;
1683 			goto err;
1684 		}
1685 
1686 		list_for_each_entry(link, &ctx->reserved_links,
1687 				    reserved_chanctx_list) {
1688 			if (!ieee80211_link_has_in_place_reservation(link))
1689 				continue;
1690 
1691 			ieee80211_chan_bw_change(local,
1692 						 ieee80211_link_get_chanctx(link),
1693 						 true, true);
1694 		}
1695 
1696 		ieee80211_recalc_chanctx_min_def(local, ctx, NULL, true);
1697 	}
1698 
1699 	/*
1700 	 * All necessary vifs are ready. Perform the switch now depending on
1701 	 * reservations and driver capabilities.
1702 	 */
1703 
1704 	if (n_vifs_switch > 0) {
1705 		err = ieee80211_chsw_switch_vifs(local, n_vifs_switch);
1706 		if (err)
1707 			goto err;
1708 	}
1709 
1710 	if (n_vifs_assign > 0 || n_vifs_ctxless > 0) {
1711 		err = ieee80211_chsw_switch_ctxs(local);
1712 		if (err)
1713 			goto err;
1714 	}
1715 
1716 	/*
1717 	 * Update all structures, values and pointers to point to new channel
1718 	 * context(s).
1719 	 */
1720 	list_for_each_entry(ctx, &local->chanctx_list, list) {
1721 		struct ieee80211_link_data *link, *link_tmp;
1722 
1723 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1724 			continue;
1725 
1726 		if (WARN_ON(!ctx->replace_ctx)) {
1727 			err = -EINVAL;
1728 			goto err;
1729 		}
1730 
1731 		list_for_each_entry(link, &ctx->reserved_links,
1732 				    reserved_chanctx_list) {
1733 			struct ieee80211_sub_if_data *sdata = link->sdata;
1734 			struct ieee80211_bss_conf *link_conf = link->conf;
1735 			u64 changed = 0;
1736 
1737 			if (!ieee80211_link_has_in_place_reservation(link))
1738 				continue;
1739 
1740 			rcu_assign_pointer(link_conf->chanctx_conf,
1741 					   &ctx->conf);
1742 
1743 			if (sdata->vif.type == NL80211_IFTYPE_AP)
1744 				__ieee80211_link_copy_chanctx_to_vlans(link,
1745 								       false);
1746 
1747 			ieee80211_check_fast_xmit_iface(sdata);
1748 
1749 			link->radar_required = link->reserved_radar_required;
1750 
1751 			if (link_conf->chanreq.oper.width != link->reserved.oper.width)
1752 				changed = BSS_CHANGED_BANDWIDTH;
1753 
1754 			ieee80211_link_update_chanreq(link, &link->reserved);
1755 			if (changed)
1756 				ieee80211_link_info_change_notify(sdata,
1757 								  link,
1758 								  changed);
1759 
1760 			ieee80211_recalc_txpower(link, false);
1761 		}
1762 
1763 		ieee80211_recalc_chanctx_chantype(local, ctx);
1764 		ieee80211_recalc_smps_chanctx(local, ctx);
1765 		ieee80211_recalc_radar_chanctx(local, ctx);
1766 		ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false);
1767 
1768 		list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
1769 					 reserved_chanctx_list) {
1770 			if (ieee80211_link_get_chanctx(link) != ctx)
1771 				continue;
1772 
1773 			list_del(&link->reserved_chanctx_list);
1774 			list_move(&link->assigned_chanctx_list,
1775 				  &ctx->assigned_links);
1776 			link->reserved_chanctx = NULL;
1777 
1778 			ieee80211_link_chanctx_reservation_complete(link);
1779 			ieee80211_chan_bw_change(local, ctx, false, false);
1780 		}
1781 
1782 		/*
1783 		 * This context might have been a dependency for an already
1784 		 * ready re-assign reservation interface that was deferred. Do
1785 		 * not propagate error to the caller though. The in-place
1786 		 * reservation for originally requested interface has already
1787 		 * succeeded at this point.
1788 		 */
1789 		list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
1790 					 reserved_chanctx_list) {
1791 			if (WARN_ON(ieee80211_link_has_in_place_reservation(link)))
1792 				continue;
1793 
1794 			if (WARN_ON(link->reserved_chanctx != ctx))
1795 				continue;
1796 
1797 			if (!link->reserved_ready)
1798 				continue;
1799 
1800 			if (ieee80211_link_get_chanctx(link))
1801 				err = ieee80211_link_use_reserved_reassign(link);
1802 			else
1803 				err = ieee80211_link_use_reserved_assign(link);
1804 
1805 			if (err) {
1806 				link_info(link,
1807 					  "failed to finalize (re-)assign reservation (err=%d)\n",
1808 					  err);
1809 				ieee80211_link_unreserve_chanctx(link);
1810 				cfg80211_stop_iface(local->hw.wiphy,
1811 						    &link->sdata->wdev,
1812 						    GFP_KERNEL);
1813 			}
1814 		}
1815 	}
1816 
1817 	/*
1818 	 * Finally free old contexts
1819 	 */
1820 
1821 	list_for_each_entry_safe(ctx, ctx_tmp, &local->chanctx_list, list) {
1822 		if (ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
1823 			continue;
1824 
1825 		ctx->replace_ctx->replace_ctx = NULL;
1826 		ctx->replace_ctx->replace_state =
1827 				IEEE80211_CHANCTX_REPLACE_NONE;
1828 
1829 		list_del_rcu(&ctx->list);
1830 		kfree_rcu(ctx, rcu_head);
1831 	}
1832 
1833 	return 0;
1834 
1835 err:
1836 	list_for_each_entry(ctx, &local->chanctx_list, list) {
1837 		struct ieee80211_link_data *link, *link_tmp;
1838 
1839 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1840 			continue;
1841 
1842 		list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
1843 					 reserved_chanctx_list) {
1844 			ieee80211_link_unreserve_chanctx(link);
1845 			ieee80211_link_chanctx_reservation_complete(link);
1846 		}
1847 	}
1848 
1849 	return err;
1850 }
1851 
1852 void __ieee80211_link_release_channel(struct ieee80211_link_data *link,
1853 				      bool skip_idle_recalc)
1854 {
1855 	struct ieee80211_sub_if_data *sdata = link->sdata;
1856 	struct ieee80211_bss_conf *link_conf = link->conf;
1857 	struct ieee80211_local *local = sdata->local;
1858 	struct ieee80211_chanctx_conf *conf;
1859 	struct ieee80211_chanctx *ctx;
1860 	bool use_reserved_switch = false;
1861 
1862 	lockdep_assert_wiphy(local->hw.wiphy);
1863 
1864 	conf = rcu_dereference_protected(link_conf->chanctx_conf,
1865 					 lockdep_is_held(&local->hw.wiphy->mtx));
1866 	if (!conf)
1867 		return;
1868 
1869 	ctx = container_of(conf, struct ieee80211_chanctx, conf);
1870 
1871 	if (link->reserved_chanctx) {
1872 		if (link->reserved_chanctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER &&
1873 		    ieee80211_chanctx_num_reserved(local, link->reserved_chanctx) > 1)
1874 			use_reserved_switch = true;
1875 
1876 		ieee80211_link_unreserve_chanctx(link);
1877 	}
1878 
1879 	ieee80211_assign_link_chanctx(link, NULL, false);
1880 	if (ieee80211_chanctx_refcount(local, ctx) == 0)
1881 		ieee80211_free_chanctx(local, ctx, skip_idle_recalc);
1882 
1883 	link->radar_required = false;
1884 
1885 	/* Unreserving may ready an in-place reservation. */
1886 	if (use_reserved_switch)
1887 		ieee80211_vif_use_reserved_switch(local);
1888 }
1889 
1890 int _ieee80211_link_use_channel(struct ieee80211_link_data *link,
1891 				const struct ieee80211_chan_req *chanreq,
1892 				enum ieee80211_chanctx_mode mode,
1893 				bool assign_on_failure)
1894 {
1895 	struct ieee80211_sub_if_data *sdata = link->sdata;
1896 	struct ieee80211_local *local = sdata->local;
1897 	struct ieee80211_chanctx *ctx;
1898 	u8 radar_detect_width = 0;
1899 	bool reserved = false;
1900 	int radio_idx;
1901 	int ret;
1902 
1903 	lockdep_assert_wiphy(local->hw.wiphy);
1904 
1905 	if (!ieee80211_vif_link_active(&sdata->vif, link->link_id)) {
1906 		ieee80211_link_update_chanreq(link, chanreq);
1907 		return 0;
1908 	}
1909 
1910 	ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
1911 					    &chanreq->oper,
1912 					    sdata->wdev.iftype);
1913 	if (ret < 0)
1914 		goto out;
1915 	if (ret > 0)
1916 		radar_detect_width = BIT(chanreq->oper.width);
1917 
1918 	link->radar_required = ret;
1919 
1920 	ret = ieee80211_check_combinations(sdata, &chanreq->oper, mode,
1921 					   radar_detect_width, -1);
1922 	if (ret < 0)
1923 		goto out;
1924 
1925 	if (!local->in_reconfig)
1926 		__ieee80211_link_release_channel(link, false);
1927 
1928 	ctx = ieee80211_find_chanctx(local, link, chanreq, mode);
1929 	/* Note: context is now reserved */
1930 	if (ctx)
1931 		reserved = true;
1932 	else if (!ieee80211_find_available_radio(local, chanreq,
1933 						 sdata->wdev.radio_mask,
1934 						 &radio_idx))
1935 		ctx = ERR_PTR(-EBUSY);
1936 	else
1937 		ctx = ieee80211_new_chanctx(local, chanreq, mode,
1938 					    assign_on_failure, radio_idx);
1939 	if (IS_ERR(ctx)) {
1940 		ret = PTR_ERR(ctx);
1941 		goto out;
1942 	}
1943 
1944 	ieee80211_link_update_chanreq(link, chanreq);
1945 
1946 	ret = ieee80211_assign_link_chanctx(link, ctx, assign_on_failure);
1947 
1948 	if (reserved) {
1949 		/* remove reservation */
1950 		WARN_ON(link->reserved_chanctx != ctx);
1951 		link->reserved_chanctx = NULL;
1952 		list_del(&link->reserved_chanctx_list);
1953 	}
1954 
1955 	if (ret) {
1956 		/* if assign fails refcount stays the same */
1957 		if (ieee80211_chanctx_refcount(local, ctx) == 0)
1958 			ieee80211_free_chanctx(local, ctx, false);
1959 		goto out;
1960 	}
1961 
1962 	ieee80211_recalc_smps_chanctx(local, ctx);
1963 	ieee80211_recalc_radar_chanctx(local, ctx);
1964  out:
1965 	if (ret)
1966 		link->radar_required = false;
1967 
1968 	return ret;
1969 }
1970 
1971 int ieee80211_link_use_reserved_context(struct ieee80211_link_data *link)
1972 {
1973 	struct ieee80211_sub_if_data *sdata = link->sdata;
1974 	struct ieee80211_local *local = sdata->local;
1975 	struct ieee80211_chanctx *new_ctx;
1976 	struct ieee80211_chanctx *old_ctx;
1977 	int err;
1978 
1979 	lockdep_assert_wiphy(local->hw.wiphy);
1980 
1981 	new_ctx = link->reserved_chanctx;
1982 	old_ctx = ieee80211_link_get_chanctx(link);
1983 
1984 	if (WARN_ON(!new_ctx))
1985 		return -EINVAL;
1986 
1987 	if (WARN_ON(new_ctx->replace_state ==
1988 		    IEEE80211_CHANCTX_WILL_BE_REPLACED))
1989 		return -EINVAL;
1990 
1991 	if (WARN_ON(link->reserved_ready))
1992 		return -EINVAL;
1993 
1994 	link->reserved_ready = true;
1995 
1996 	if (new_ctx->replace_state == IEEE80211_CHANCTX_REPLACE_NONE) {
1997 		if (old_ctx)
1998 			return ieee80211_link_use_reserved_reassign(link);
1999 
2000 		return ieee80211_link_use_reserved_assign(link);
2001 	}
2002 
2003 	/*
2004 	 * In-place reservation may need to be finalized now either if:
2005 	 *  a) sdata is taking part in the swapping itself and is the last one
2006 	 *  b) sdata has switched with a re-assign reservation to an existing
2007 	 *     context readying in-place switching of old_ctx
2008 	 *
2009 	 * In case of (b) do not propagate the error up because the requested
2010 	 * sdata already switched successfully. Just spill an extra warning.
2011 	 * The ieee80211_vif_use_reserved_switch() already stops all necessary
2012 	 * interfaces upon failure.
2013 	 */
2014 	if ((old_ctx &&
2015 	     old_ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
2016 	    new_ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
2017 		err = ieee80211_vif_use_reserved_switch(local);
2018 		if (err && err != -EAGAIN) {
2019 			if (new_ctx->replace_state ==
2020 			    IEEE80211_CHANCTX_REPLACES_OTHER)
2021 				return err;
2022 
2023 			wiphy_info(local->hw.wiphy,
2024 				   "depending in-place reservation failed (err=%d)\n",
2025 				   err);
2026 		}
2027 	}
2028 
2029 	return 0;
2030 }
2031 
2032 /*
2033  * This is similar to ieee80211_chanctx_compatible(), but rechecks
2034  * against all the links actually using it (except the one that's
2035  * passed, since that one is changing).
2036  * This is done in order to allow changes to the AP's bandwidth for
2037  * wider bandwidth OFDMA purposes, which wouldn't be treated as
2038  * compatible by ieee80211_chanctx_recheck() but is OK if the link
2039  * requesting the update is the only one using it.
2040  */
2041 static const struct ieee80211_chan_req *
2042 ieee80211_chanctx_recheck(struct ieee80211_local *local,
2043 			  struct ieee80211_link_data *skip_link,
2044 			  struct ieee80211_chanctx *ctx,
2045 			  const struct ieee80211_chan_req *req,
2046 			  struct ieee80211_chan_req *tmp)
2047 {
2048 	const struct ieee80211_chan_req *ret = req;
2049 	struct ieee80211_link_data *link;
2050 
2051 	lockdep_assert_wiphy(local->hw.wiphy);
2052 
2053 	for_each_sdata_link(local, link) {
2054 		if (link == skip_link)
2055 			continue;
2056 
2057 		if (rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf) {
2058 			ret = ieee80211_chanreq_compatible(ret,
2059 							   &link->conf->chanreq,
2060 							   tmp);
2061 			if (!ret)
2062 				return NULL;
2063 		}
2064 
2065 		if (link->reserved_chanctx == ctx) {
2066 			ret = ieee80211_chanreq_compatible(ret,
2067 							   &link->reserved,
2068 							   tmp);
2069 			if (!ret)
2070 				return NULL;
2071 		}
2072 	}
2073 
2074 	*tmp = *ret;
2075 	return tmp;
2076 }
2077 
2078 int ieee80211_link_change_chanreq(struct ieee80211_link_data *link,
2079 				  const struct ieee80211_chan_req *chanreq,
2080 				  u64 *changed)
2081 {
2082 	struct ieee80211_sub_if_data *sdata = link->sdata;
2083 	struct ieee80211_bss_conf *link_conf = link->conf;
2084 	struct ieee80211_local *local = sdata->local;
2085 	struct ieee80211_chanctx_conf *conf;
2086 	struct ieee80211_chanctx *ctx;
2087 	const struct ieee80211_chan_req *compat;
2088 	struct ieee80211_chan_req tmp;
2089 
2090 	lockdep_assert_wiphy(local->hw.wiphy);
2091 
2092 	if (!cfg80211_chandef_usable(sdata->local->hw.wiphy,
2093 				     &chanreq->oper,
2094 				     IEEE80211_CHAN_DISABLED))
2095 		return -EINVAL;
2096 
2097 	/* for non-HT 20 MHz the rest doesn't matter */
2098 	if (chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT &&
2099 	    cfg80211_chandef_identical(&chanreq->oper, &link_conf->chanreq.oper))
2100 		return 0;
2101 
2102 	/* but you cannot switch to/from it */
2103 	if (chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT ||
2104 	    link_conf->chanreq.oper.width == NL80211_CHAN_WIDTH_20_NOHT)
2105 		return -EINVAL;
2106 
2107 	conf = rcu_dereference_protected(link_conf->chanctx_conf,
2108 					 lockdep_is_held(&local->hw.wiphy->mtx));
2109 	if (!conf)
2110 		return -EINVAL;
2111 
2112 	ctx = container_of(conf, struct ieee80211_chanctx, conf);
2113 
2114 	compat = ieee80211_chanctx_recheck(local, link, ctx, chanreq, &tmp);
2115 	if (!compat)
2116 		return -EINVAL;
2117 
2118 	switch (ctx->replace_state) {
2119 	case IEEE80211_CHANCTX_REPLACE_NONE:
2120 		if (!ieee80211_chanctx_reserved_chanreq(local, ctx, compat,
2121 							&tmp))
2122 			return -EBUSY;
2123 		break;
2124 	case IEEE80211_CHANCTX_WILL_BE_REPLACED:
2125 		/* TODO: Perhaps the bandwidth change could be treated as a
2126 		 * reservation itself? */
2127 		return -EBUSY;
2128 	case IEEE80211_CHANCTX_REPLACES_OTHER:
2129 		/* channel context that is going to replace another channel
2130 		 * context doesn't really exist and shouldn't be assigned
2131 		 * anywhere yet */
2132 		WARN_ON(1);
2133 		break;
2134 	}
2135 
2136 	ieee80211_link_update_chanreq(link, chanreq);
2137 
2138 	ieee80211_recalc_chanctx_chantype(local, ctx);
2139 
2140 	*changed |= BSS_CHANGED_BANDWIDTH;
2141 	return 0;
2142 }
2143 
2144 void ieee80211_link_release_channel(struct ieee80211_link_data *link)
2145 {
2146 	struct ieee80211_sub_if_data *sdata = link->sdata;
2147 
2148 	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
2149 		return;
2150 
2151 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
2152 
2153 	if (rcu_access_pointer(link->conf->chanctx_conf))
2154 		__ieee80211_link_release_channel(link, false);
2155 }
2156 
2157 void ieee80211_link_vlan_copy_chanctx(struct ieee80211_link_data *link)
2158 {
2159 	struct ieee80211_sub_if_data *sdata = link->sdata;
2160 	unsigned int link_id = link->link_id;
2161 	struct ieee80211_bss_conf *link_conf = link->conf;
2162 	struct ieee80211_bss_conf *ap_conf;
2163 	struct ieee80211_local *local = sdata->local;
2164 	struct ieee80211_sub_if_data *ap;
2165 	struct ieee80211_chanctx_conf *conf;
2166 
2167 	lockdep_assert_wiphy(local->hw.wiphy);
2168 
2169 	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
2170 		return;
2171 
2172 	ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
2173 
2174 	ap_conf = wiphy_dereference(local->hw.wiphy,
2175 				    ap->vif.link_conf[link_id]);
2176 	conf = wiphy_dereference(local->hw.wiphy,
2177 				 ap_conf->chanctx_conf);
2178 	rcu_assign_pointer(link_conf->chanctx_conf, conf);
2179 }
2180 
2181 void ieee80211_iter_chan_contexts_atomic(
2182 	struct ieee80211_hw *hw,
2183 	void (*iter)(struct ieee80211_hw *hw,
2184 		     struct ieee80211_chanctx_conf *chanctx_conf,
2185 		     void *data),
2186 	void *iter_data)
2187 {
2188 	struct ieee80211_local *local = hw_to_local(hw);
2189 	struct ieee80211_chanctx *ctx;
2190 
2191 	rcu_read_lock();
2192 	list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
2193 		if (ctx->driver_present)
2194 			iter(hw, &ctx->conf, iter_data);
2195 	rcu_read_unlock();
2196 }
2197 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);
2198 
2199 void ieee80211_iter_chan_contexts_mtx(
2200 	struct ieee80211_hw *hw,
2201 	void (*iter)(struct ieee80211_hw *hw,
2202 		     struct ieee80211_chanctx_conf *chanctx_conf,
2203 		     void *data),
2204 	void *iter_data)
2205 {
2206 	struct ieee80211_local *local = hw_to_local(hw);
2207 	struct ieee80211_chanctx *ctx;
2208 
2209 	lockdep_assert_wiphy(hw->wiphy);
2210 
2211 	list_for_each_entry(ctx, &local->chanctx_list, list)
2212 		if (ctx->driver_present)
2213 			iter(hw, &ctx->conf, iter_data);
2214 }
2215 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_mtx);
2216