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