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