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