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