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