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