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