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