1 // SPDX-License-Identifier: GPL-2.0-only
3 * mac80211 - channel management
4 * Copyright 2020 - 2024 Intel Corporation
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"
15 static int ieee80211_chanctx_num_assigned(struct ieee80211_local
*local
,
16 struct ieee80211_chanctx
*ctx
)
18 struct ieee80211_link_data
*link
;
21 lockdep_assert_wiphy(local
->hw
.wiphy
);
23 list_for_each_entry(link
, &ctx
->assigned_links
, assigned_chanctx_list
)
29 static int ieee80211_chanctx_num_reserved(struct ieee80211_local
*local
,
30 struct ieee80211_chanctx
*ctx
)
32 struct ieee80211_link_data
*link
;
35 lockdep_assert_wiphy(local
->hw
.wiphy
);
37 list_for_each_entry(link
, &ctx
->reserved_links
, reserved_chanctx_list
)
43 int ieee80211_chanctx_refcount(struct ieee80211_local
*local
,
44 struct ieee80211_chanctx
*ctx
)
46 return ieee80211_chanctx_num_assigned(local
, ctx
) +
47 ieee80211_chanctx_num_reserved(local
, ctx
);
50 static int ieee80211_num_chanctx(struct ieee80211_local
*local
, int radio_idx
)
52 struct ieee80211_chanctx
*ctx
;
55 lockdep_assert_wiphy(local
->hw
.wiphy
);
57 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
58 if (radio_idx
>= 0 && ctx
->conf
.radio_idx
!= radio_idx
)
66 static bool ieee80211_can_create_new_chanctx(struct ieee80211_local
*local
,
69 lockdep_assert_wiphy(local
->hw
.wiphy
);
71 return ieee80211_num_chanctx(local
, radio_idx
) <
72 ieee80211_max_num_channels(local
, radio_idx
);
75 static struct ieee80211_chanctx
*
76 ieee80211_link_get_chanctx(struct ieee80211_link_data
*link
)
78 struct ieee80211_local
*local __maybe_unused
= link
->sdata
->local
;
79 struct ieee80211_chanctx_conf
*conf
;
81 conf
= rcu_dereference_protected(link
->conf
->chanctx_conf
,
82 lockdep_is_held(&local
->hw
.wiphy
->mtx
));
86 return container_of(conf
, struct ieee80211_chanctx
, conf
);
89 bool ieee80211_chanreq_identical(const struct ieee80211_chan_req
*a
,
90 const struct ieee80211_chan_req
*b
)
92 if (!cfg80211_chandef_identical(&a
->oper
, &b
->oper
))
94 if (!a
->ap
.chan
&& !b
->ap
.chan
)
96 return cfg80211_chandef_identical(&a
->ap
, &b
->ap
);
99 static const struct ieee80211_chan_req
*
100 ieee80211_chanreq_compatible(const struct ieee80211_chan_req
*a
,
101 const struct ieee80211_chan_req
*b
,
102 struct ieee80211_chan_req
*tmp
)
104 const struct cfg80211_chan_def
*compat
;
106 if (a
->ap
.chan
&& b
->ap
.chan
&&
107 !cfg80211_chandef_identical(&a
->ap
, &b
->ap
))
110 compat
= cfg80211_chandef_compatible(&a
->oper
, &b
->oper
);
114 /* Note: later code assumes this always fills & returns tmp if compat */
116 tmp
->ap
= a
->ap
.chan
? a
->ap
: b
->ap
;
120 static const struct ieee80211_chan_req
*
121 ieee80211_chanctx_compatible(struct ieee80211_chanctx
*ctx
,
122 const struct ieee80211_chan_req
*req
,
123 struct ieee80211_chan_req
*tmp
)
125 const struct ieee80211_chan_req
*ret
;
126 struct ieee80211_chan_req tmp2
;
128 *tmp
= (struct ieee80211_chan_req
){
129 .oper
= ctx
->conf
.def
,
133 ret
= ieee80211_chanreq_compatible(tmp
, req
, &tmp2
);
140 static const struct ieee80211_chan_req
*
141 ieee80211_chanctx_reserved_chanreq(struct ieee80211_local
*local
,
142 struct ieee80211_chanctx
*ctx
,
143 const struct ieee80211_chan_req
*req
,
144 struct ieee80211_chan_req
*tmp
)
146 struct ieee80211_link_data
*link
;
148 lockdep_assert_wiphy(local
->hw
.wiphy
);
153 list_for_each_entry(link
, &ctx
->reserved_links
, reserved_chanctx_list
) {
154 req
= ieee80211_chanreq_compatible(&link
->reserved
, req
, tmp
);
162 static const struct ieee80211_chan_req
*
163 ieee80211_chanctx_non_reserved_chandef(struct ieee80211_local
*local
,
164 struct ieee80211_chanctx
*ctx
,
165 const struct ieee80211_chan_req
*compat
,
166 struct ieee80211_chan_req
*tmp
)
168 struct ieee80211_link_data
*link
;
169 const struct ieee80211_chan_req
*comp_def
= compat
;
171 lockdep_assert_wiphy(local
->hw
.wiphy
);
173 list_for_each_entry(link
, &ctx
->assigned_links
, assigned_chanctx_list
) {
174 struct ieee80211_bss_conf
*link_conf
= link
->conf
;
176 if (link
->reserved_chanctx
)
179 comp_def
= ieee80211_chanreq_compatible(&link_conf
->chanreq
,
189 ieee80211_chanctx_can_reserve(struct ieee80211_local
*local
,
190 struct ieee80211_chanctx
*ctx
,
191 const struct ieee80211_chan_req
*req
)
193 struct ieee80211_chan_req tmp
;
195 lockdep_assert_wiphy(local
->hw
.wiphy
);
197 if (!ieee80211_chanctx_reserved_chanreq(local
, ctx
, req
, &tmp
))
200 if (!ieee80211_chanctx_non_reserved_chandef(local
, ctx
, req
, &tmp
))
203 if (!list_empty(&ctx
->reserved_links
) &&
204 ieee80211_chanctx_reserved_chanreq(local
, ctx
, req
, &tmp
))
210 static struct ieee80211_chanctx
*
211 ieee80211_find_reservation_chanctx(struct ieee80211_local
*local
,
212 const struct ieee80211_chan_req
*chanreq
,
213 enum ieee80211_chanctx_mode mode
)
215 struct ieee80211_chanctx
*ctx
;
217 lockdep_assert_wiphy(local
->hw
.wiphy
);
219 if (mode
== IEEE80211_CHANCTX_EXCLUSIVE
)
222 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
223 if (ctx
->replace_state
== IEEE80211_CHANCTX_WILL_BE_REPLACED
)
226 if (ctx
->mode
== IEEE80211_CHANCTX_EXCLUSIVE
)
229 if (!ieee80211_chanctx_can_reserve(local
, ctx
, chanreq
))
238 static enum nl80211_chan_width
ieee80211_get_sta_bw(struct sta_info
*sta
,
239 unsigned int link_id
)
241 enum ieee80211_sta_rx_bandwidth width
;
242 struct link_sta_info
*link_sta
;
244 link_sta
= wiphy_dereference(sta
->local
->hw
.wiphy
, sta
->link
[link_id
]);
246 /* no effect if this STA has no presence on this link */
248 return NL80211_CHAN_WIDTH_20_NOHT
;
250 width
= ieee80211_sta_cap_rx_bw(link_sta
);
253 case IEEE80211_STA_RX_BW_20
:
254 if (link_sta
->pub
->ht_cap
.ht_supported
)
255 return NL80211_CHAN_WIDTH_20
;
257 return NL80211_CHAN_WIDTH_20_NOHT
;
258 case IEEE80211_STA_RX_BW_40
:
259 return NL80211_CHAN_WIDTH_40
;
260 case IEEE80211_STA_RX_BW_80
:
261 return NL80211_CHAN_WIDTH_80
;
262 case IEEE80211_STA_RX_BW_160
:
264 * This applied for both 160 and 80+80. since we use
265 * the returned value to consider degradation of
266 * ctx->conf.min_def, we have to make sure to take
267 * the bigger one (NL80211_CHAN_WIDTH_160).
268 * Otherwise we might try degrading even when not
269 * needed, as the max required sta_bw returned (80+80)
270 * might be smaller than the configured bw (160).
272 return NL80211_CHAN_WIDTH_160
;
273 case IEEE80211_STA_RX_BW_320
:
274 return NL80211_CHAN_WIDTH_320
;
277 return NL80211_CHAN_WIDTH_20
;
281 static enum nl80211_chan_width
282 ieee80211_get_max_required_bw(struct ieee80211_link_data
*link
)
284 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
285 unsigned int link_id
= link
->link_id
;
286 enum nl80211_chan_width max_bw
= NL80211_CHAN_WIDTH_20_NOHT
;
287 struct sta_info
*sta
;
289 lockdep_assert_wiphy(sdata
->local
->hw
.wiphy
);
291 list_for_each_entry(sta
, &sdata
->local
->sta_list
, list
) {
292 if (sdata
!= sta
->sdata
&&
293 !(sta
->sdata
->bss
&& sta
->sdata
->bss
== sdata
->bss
))
296 max_bw
= max(max_bw
, ieee80211_get_sta_bw(sta
, link_id
));
302 static enum nl80211_chan_width
303 ieee80211_get_chanctx_max_required_bw(struct ieee80211_local
*local
,
304 struct ieee80211_chanctx
*ctx
,
305 struct ieee80211_link_data
*rsvd_for
,
308 struct ieee80211_sub_if_data
*sdata
;
309 struct ieee80211_link_data
*link
;
310 enum nl80211_chan_width max_bw
= NL80211_CHAN_WIDTH_20_NOHT
;
312 if (WARN_ON(check_reserved
&& rsvd_for
))
313 return ctx
->conf
.def
.width
;
315 for_each_sdata_link(local
, link
) {
316 enum nl80211_chan_width width
= NL80211_CHAN_WIDTH_20_NOHT
;
318 if (check_reserved
) {
319 if (link
->reserved_chanctx
!= ctx
)
321 } else if (link
!= rsvd_for
&&
322 rcu_access_pointer(link
->conf
->chanctx_conf
) != &ctx
->conf
)
325 switch (link
->sdata
->vif
.type
) {
326 case NL80211_IFTYPE_STATION
:
327 if (!link
->sdata
->vif
.cfg
.assoc
) {
329 * The AP's sta->bandwidth may not yet be set
330 * at this point (pre-association), so simply
331 * take the width from the chandef. We cannot
332 * have TDLS peers yet (only after association).
334 width
= link
->conf
->chanreq
.oper
.width
;
338 * otherwise just use min_def like in AP, depending on what
339 * we currently think the AP STA (and possibly TDLS peers)
343 case NL80211_IFTYPE_AP
:
344 case NL80211_IFTYPE_AP_VLAN
:
345 width
= ieee80211_get_max_required_bw(link
);
347 case NL80211_IFTYPE_P2P_DEVICE
:
348 case NL80211_IFTYPE_NAN
:
350 case NL80211_IFTYPE_MONITOR
:
351 WARN_ON_ONCE(!ieee80211_hw_check(&local
->hw
,
352 NO_VIRTUAL_MONITOR
));
354 case NL80211_IFTYPE_ADHOC
:
355 case NL80211_IFTYPE_MESH_POINT
:
356 case NL80211_IFTYPE_OCB
:
357 width
= link
->conf
->chanreq
.oper
.width
;
359 case NL80211_IFTYPE_WDS
:
360 case NL80211_IFTYPE_UNSPECIFIED
:
361 case NUM_NL80211_IFTYPES
:
362 case NL80211_IFTYPE_P2P_CLIENT
:
363 case NL80211_IFTYPE_P2P_GO
:
367 max_bw
= max(max_bw
, width
);
370 /* use the configured bandwidth in case of monitor interface */
371 sdata
= wiphy_dereference(local
->hw
.wiphy
, local
->monitor_sdata
);
373 rcu_access_pointer(sdata
->vif
.bss_conf
.chanctx_conf
) == &ctx
->conf
)
374 max_bw
= max(max_bw
, ctx
->conf
.def
.width
);
380 * recalc the min required chan width of the channel context, which is
381 * the max of min required widths of all the interfaces bound to this
385 _ieee80211_recalc_chanctx_min_def(struct ieee80211_local
*local
,
386 struct ieee80211_chanctx
*ctx
,
387 struct ieee80211_link_data
*rsvd_for
,
390 enum nl80211_chan_width max_bw
;
391 struct cfg80211_chan_def min_def
;
393 lockdep_assert_wiphy(local
->hw
.wiphy
);
395 /* don't optimize non-20MHz based and radar_enabled confs */
396 if (ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_5
||
397 ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_10
||
398 ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_1
||
399 ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_2
||
400 ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_4
||
401 ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_8
||
402 ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_16
||
403 ctx
->conf
.radar_enabled
) {
404 ctx
->conf
.min_def
= ctx
->conf
.def
;
408 max_bw
= ieee80211_get_chanctx_max_required_bw(local
, ctx
, rsvd_for
,
411 /* downgrade chandef up to max_bw */
412 min_def
= ctx
->conf
.def
;
413 while (min_def
.width
> max_bw
)
414 ieee80211_chandef_downgrade(&min_def
, NULL
);
416 if (cfg80211_chandef_identical(&ctx
->conf
.min_def
, &min_def
))
419 ctx
->conf
.min_def
= min_def
;
420 if (!ctx
->driver_present
)
423 return IEEE80211_CHANCTX_CHANGE_MIN_DEF
;
426 static void ieee80211_chan_bw_change(struct ieee80211_local
*local
,
427 struct ieee80211_chanctx
*ctx
,
428 bool reserved
, bool narrowed
)
430 struct sta_info
*sta
;
431 struct ieee80211_supported_band
*sband
=
432 local
->hw
.wiphy
->bands
[ctx
->conf
.def
.chan
->band
];
435 list_for_each_entry_rcu(sta
, &local
->sta_list
,
437 struct ieee80211_sub_if_data
*sdata
= sta
->sdata
;
438 enum ieee80211_sta_rx_bandwidth new_sta_bw
;
439 unsigned int link_id
;
441 if (!ieee80211_sdata_running(sta
->sdata
))
444 for (link_id
= 0; link_id
< ARRAY_SIZE(sta
->sdata
->link
); link_id
++) {
445 struct ieee80211_link_data
*link
=
446 rcu_dereference(sdata
->link
[link_id
]);
447 struct ieee80211_bss_conf
*link_conf
;
448 struct cfg80211_chan_def
*new_chandef
;
449 struct link_sta_info
*link_sta
;
454 link_conf
= link
->conf
;
456 if (rcu_access_pointer(link_conf
->chanctx_conf
) != &ctx
->conf
)
459 link_sta
= rcu_dereference(sta
->link
[link_id
]);
464 new_chandef
= &link
->reserved
.oper
;
466 new_chandef
= &link_conf
->chanreq
.oper
;
468 new_sta_bw
= _ieee80211_sta_cur_vht_bw(link_sta
,
472 if (new_sta_bw
== link_sta
->pub
->bandwidth
)
475 /* vif changed to narrow BW and narrow BW for station wasn't
476 * requested or vice versa */
477 if ((new_sta_bw
< link_sta
->pub
->bandwidth
) == !narrowed
)
480 link_sta
->pub
->bandwidth
= new_sta_bw
;
481 rate_control_rate_update(local
, sband
, link_sta
,
482 IEEE80211_RC_BW_CHANGED
);
489 * recalc the min required chan width of the channel context, which is
490 * the max of min required widths of all the interfaces bound to this
493 void ieee80211_recalc_chanctx_min_def(struct ieee80211_local
*local
,
494 struct ieee80211_chanctx
*ctx
,
495 struct ieee80211_link_data
*rsvd_for
,
498 u32 changed
= _ieee80211_recalc_chanctx_min_def(local
, ctx
, rsvd_for
,
504 /* check is BW narrowed */
505 ieee80211_chan_bw_change(local
, ctx
, false, true);
507 drv_change_chanctx(local
, ctx
, changed
);
509 /* check is BW wider */
510 ieee80211_chan_bw_change(local
, ctx
, false, false);
513 static void _ieee80211_change_chanctx(struct ieee80211_local
*local
,
514 struct ieee80211_chanctx
*ctx
,
515 struct ieee80211_chanctx
*old_ctx
,
516 const struct ieee80211_chan_req
*chanreq
,
517 struct ieee80211_link_data
*rsvd_for
)
519 const struct cfg80211_chan_def
*chandef
= &chanreq
->oper
;
520 struct ieee80211_chan_req ctx_req
= {
521 .oper
= ctx
->conf
.def
,
526 /* expected to handle only 20/40/80/160/320 channel widths */
527 switch (chandef
->width
) {
528 case NL80211_CHAN_WIDTH_20_NOHT
:
529 case NL80211_CHAN_WIDTH_20
:
530 case NL80211_CHAN_WIDTH_40
:
531 case NL80211_CHAN_WIDTH_80
:
532 case NL80211_CHAN_WIDTH_80P80
:
533 case NL80211_CHAN_WIDTH_160
:
534 case NL80211_CHAN_WIDTH_320
:
540 /* Check maybe BW narrowed - we do this _before_ calling recalc_chanctx_min_def
541 * due to maybe not returning from it, e.g in case new context was added
542 * first time with all parameters up to date.
544 ieee80211_chan_bw_change(local
, old_ctx
, false, true);
546 if (ieee80211_chanreq_identical(&ctx_req
, chanreq
)) {
547 ieee80211_recalc_chanctx_min_def(local
, ctx
, rsvd_for
, false);
551 WARN_ON(ieee80211_chanctx_refcount(local
, ctx
) > 1 &&
552 !cfg80211_chandef_compatible(&ctx
->conf
.def
, &chanreq
->oper
));
554 ieee80211_remove_wbrf(local
, &ctx
->conf
.def
);
556 if (!cfg80211_chandef_identical(&ctx
->conf
.def
, &chanreq
->oper
)) {
557 if (ctx
->conf
.def
.width
!= chanreq
->oper
.width
)
558 changed
|= IEEE80211_CHANCTX_CHANGE_WIDTH
;
559 if (ctx
->conf
.def
.punctured
!= chanreq
->oper
.punctured
)
560 changed
|= IEEE80211_CHANCTX_CHANGE_PUNCTURING
;
562 if (!cfg80211_chandef_identical(&ctx
->conf
.ap
, &chanreq
->ap
))
563 changed
|= IEEE80211_CHANCTX_CHANGE_AP
;
564 ctx
->conf
.def
= *chandef
;
565 ctx
->conf
.ap
= chanreq
->ap
;
567 /* check if min chanctx also changed */
568 changed
|= _ieee80211_recalc_chanctx_min_def(local
, ctx
, rsvd_for
, false);
570 ieee80211_add_wbrf(local
, &ctx
->conf
.def
);
572 drv_change_chanctx(local
, ctx
, changed
);
574 /* check if BW is wider */
575 ieee80211_chan_bw_change(local
, old_ctx
, false, false);
578 static void ieee80211_change_chanctx(struct ieee80211_local
*local
,
579 struct ieee80211_chanctx
*ctx
,
580 struct ieee80211_chanctx
*old_ctx
,
581 const struct ieee80211_chan_req
*chanreq
)
583 _ieee80211_change_chanctx(local
, ctx
, old_ctx
, chanreq
, NULL
);
586 /* Note: if successful, the returned chanctx is reserved for the link */
587 static struct ieee80211_chanctx
*
588 ieee80211_find_chanctx(struct ieee80211_local
*local
,
589 struct ieee80211_link_data
*link
,
590 const struct ieee80211_chan_req
*chanreq
,
591 enum ieee80211_chanctx_mode mode
)
593 struct ieee80211_chan_req tmp
;
594 struct ieee80211_chanctx
*ctx
;
596 lockdep_assert_wiphy(local
->hw
.wiphy
);
598 if (mode
== IEEE80211_CHANCTX_EXCLUSIVE
)
601 if (WARN_ON(link
->reserved_chanctx
))
604 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
605 const struct ieee80211_chan_req
*compat
;
607 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACE_NONE
)
610 if (ctx
->mode
== IEEE80211_CHANCTX_EXCLUSIVE
)
613 compat
= ieee80211_chanctx_compatible(ctx
, chanreq
, &tmp
);
617 compat
= ieee80211_chanctx_reserved_chanreq(local
, ctx
,
623 * Reserve the chanctx temporarily, as the driver might change
624 * active links during callbacks we make into it below and/or
625 * later during assignment, which could (otherwise) cause the
626 * context to actually be removed.
628 link
->reserved_chanctx
= ctx
;
629 list_add(&link
->reserved_chanctx_list
,
630 &ctx
->reserved_links
);
632 ieee80211_change_chanctx(local
, ctx
, ctx
, compat
);
640 bool ieee80211_is_radar_required(struct ieee80211_local
*local
)
642 struct ieee80211_link_data
*link
;
644 lockdep_assert_wiphy(local
->hw
.wiphy
);
646 for_each_sdata_link(local
, link
) {
647 if (link
->radar_required
)
655 ieee80211_chanctx_radar_required(struct ieee80211_local
*local
,
656 struct ieee80211_chanctx
*ctx
)
658 struct ieee80211_chanctx_conf
*conf
= &ctx
->conf
;
659 struct ieee80211_link_data
*link
;
661 lockdep_assert_wiphy(local
->hw
.wiphy
);
663 for_each_sdata_link(local
, link
) {
664 if (rcu_access_pointer(link
->conf
->chanctx_conf
) != conf
)
666 if (!link
->radar_required
)
674 static struct ieee80211_chanctx
*
675 ieee80211_alloc_chanctx(struct ieee80211_local
*local
,
676 const struct ieee80211_chan_req
*chanreq
,
677 enum ieee80211_chanctx_mode mode
,
680 struct ieee80211_chanctx
*ctx
;
682 lockdep_assert_wiphy(local
->hw
.wiphy
);
684 ctx
= kzalloc(sizeof(*ctx
) + local
->hw
.chanctx_data_size
, GFP_KERNEL
);
688 INIT_LIST_HEAD(&ctx
->assigned_links
);
689 INIT_LIST_HEAD(&ctx
->reserved_links
);
690 ctx
->conf
.def
= chanreq
->oper
;
691 ctx
->conf
.ap
= chanreq
->ap
;
692 ctx
->conf
.rx_chains_static
= 1;
693 ctx
->conf
.rx_chains_dynamic
= 1;
695 ctx
->conf
.radar_enabled
= false;
696 ctx
->conf
.radio_idx
= radio_idx
;
697 ctx
->radar_detected
= false;
698 _ieee80211_recalc_chanctx_min_def(local
, ctx
, NULL
, false);
703 static int ieee80211_add_chanctx(struct ieee80211_local
*local
,
704 struct ieee80211_chanctx
*ctx
)
709 lockdep_assert_wiphy(local
->hw
.wiphy
);
711 ieee80211_add_wbrf(local
, &ctx
->conf
.def
);
713 /* turn idle off *before* setting channel -- some drivers need that */
714 changed
= ieee80211_idle_off(local
);
716 ieee80211_hw_config(local
, changed
);
718 err
= drv_add_chanctx(local
, ctx
);
720 ieee80211_recalc_idle(local
);
727 static struct ieee80211_chanctx
*
728 ieee80211_new_chanctx(struct ieee80211_local
*local
,
729 const struct ieee80211_chan_req
*chanreq
,
730 enum ieee80211_chanctx_mode mode
,
731 bool assign_on_failure
,
734 struct ieee80211_chanctx
*ctx
;
737 lockdep_assert_wiphy(local
->hw
.wiphy
);
739 ctx
= ieee80211_alloc_chanctx(local
, chanreq
, mode
, radio_idx
);
741 return ERR_PTR(-ENOMEM
);
743 err
= ieee80211_add_chanctx(local
, ctx
);
744 if (!assign_on_failure
&& err
) {
748 /* We ignored a driver error, see _ieee80211_set_active_links */
749 WARN_ON_ONCE(err
&& !local
->in_reconfig
);
751 list_add_rcu(&ctx
->list
, &local
->chanctx_list
);
755 static void ieee80211_del_chanctx(struct ieee80211_local
*local
,
756 struct ieee80211_chanctx
*ctx
,
757 bool skip_idle_recalc
)
759 lockdep_assert_wiphy(local
->hw
.wiphy
);
761 drv_remove_chanctx(local
, ctx
);
763 if (!skip_idle_recalc
)
764 ieee80211_recalc_idle(local
);
766 ieee80211_remove_wbrf(local
, &ctx
->conf
.def
);
769 static void ieee80211_free_chanctx(struct ieee80211_local
*local
,
770 struct ieee80211_chanctx
*ctx
,
771 bool skip_idle_recalc
)
773 lockdep_assert_wiphy(local
->hw
.wiphy
);
775 WARN_ON_ONCE(ieee80211_chanctx_refcount(local
, ctx
) != 0);
777 list_del_rcu(&ctx
->list
);
778 ieee80211_del_chanctx(local
, ctx
, skip_idle_recalc
);
779 kfree_rcu(ctx
, rcu_head
);
782 void ieee80211_recalc_chanctx_chantype(struct ieee80211_local
*local
,
783 struct ieee80211_chanctx
*ctx
)
785 struct ieee80211_chanctx_conf
*conf
= &ctx
->conf
;
786 const struct ieee80211_chan_req
*compat
= NULL
;
787 struct ieee80211_link_data
*link
;
788 struct ieee80211_chan_req tmp
;
789 struct sta_info
*sta
;
791 lockdep_assert_wiphy(local
->hw
.wiphy
);
793 for_each_sdata_link(local
, link
) {
794 struct ieee80211_bss_conf
*link_conf
;
796 if (link
->sdata
->vif
.type
== NL80211_IFTYPE_AP_VLAN
)
799 link_conf
= link
->conf
;
801 if (rcu_access_pointer(link_conf
->chanctx_conf
) != conf
)
805 compat
= &link_conf
->chanreq
;
807 compat
= ieee80211_chanreq_compatible(&link_conf
->chanreq
,
809 if (WARN_ON_ONCE(!compat
))
813 if (WARN_ON_ONCE(!compat
))
816 /* TDLS peers can sometimes affect the chandef width */
817 list_for_each_entry(sta
, &local
->sta_list
, list
) {
818 struct ieee80211_sub_if_data
*sdata
= sta
->sdata
;
819 struct ieee80211_chan_req tdls_chanreq
= {};
822 if (!sta
->uploaded
||
823 !test_sta_flag(sta
, WLAN_STA_TDLS_WIDER_BW
) ||
824 !test_sta_flag(sta
, WLAN_STA_AUTHORIZED
) ||
825 !sta
->tdls_chandef
.chan
)
828 tdls_link_id
= ieee80211_tdls_sta_link_id(sta
);
829 link
= sdata_dereference(sdata
->link
[tdls_link_id
], sdata
);
833 if (rcu_access_pointer(link
->conf
->chanctx_conf
) != conf
)
836 tdls_chanreq
.oper
= sta
->tdls_chandef
;
838 /* note this always fills and returns &tmp if compat */
839 compat
= ieee80211_chanreq_compatible(&tdls_chanreq
,
841 if (WARN_ON_ONCE(!compat
))
845 ieee80211_change_chanctx(local
, ctx
, ctx
, compat
);
848 static void ieee80211_recalc_radar_chanctx(struct ieee80211_local
*local
,
849 struct ieee80211_chanctx
*chanctx
)
853 lockdep_assert_wiphy(local
->hw
.wiphy
);
855 radar_enabled
= ieee80211_chanctx_radar_required(local
, chanctx
);
857 if (radar_enabled
== chanctx
->conf
.radar_enabled
)
860 chanctx
->conf
.radar_enabled
= radar_enabled
;
862 drv_change_chanctx(local
, chanctx
, IEEE80211_CHANCTX_CHANGE_RADAR
);
865 static int ieee80211_assign_link_chanctx(struct ieee80211_link_data
*link
,
866 struct ieee80211_chanctx
*new_ctx
,
867 bool assign_on_failure
)
869 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
870 struct ieee80211_local
*local
= sdata
->local
;
871 struct ieee80211_chanctx_conf
*conf
;
872 struct ieee80211_chanctx
*curr_ctx
= NULL
;
876 if (WARN_ON(sdata
->vif
.type
== NL80211_IFTYPE_NAN
))
879 conf
= rcu_dereference_protected(link
->conf
->chanctx_conf
,
880 lockdep_is_held(&local
->hw
.wiphy
->mtx
));
883 curr_ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
885 drv_unassign_vif_chanctx(local
, sdata
, link
->conf
, curr_ctx
);
887 list_del(&link
->assigned_chanctx_list
);
891 /* recalc considering the link we'll use it for now */
892 ieee80211_recalc_chanctx_min_def(local
, new_ctx
, link
, false);
894 ret
= drv_assign_vif_chanctx(local
, sdata
, link
->conf
, new_ctx
);
895 if (assign_on_failure
|| !ret
) {
896 /* Need to continue, see _ieee80211_set_active_links */
897 WARN_ON_ONCE(ret
&& !local
->in_reconfig
);
900 /* succeeded, so commit it to the data structures */
901 conf
= &new_ctx
->conf
;
902 list_add(&link
->assigned_chanctx_list
,
903 &new_ctx
->assigned_links
);
909 rcu_assign_pointer(link
->conf
->chanctx_conf
, conf
);
911 if (curr_ctx
&& ieee80211_chanctx_num_assigned(local
, curr_ctx
) > 0) {
912 ieee80211_recalc_chanctx_chantype(local
, curr_ctx
);
913 ieee80211_recalc_smps_chanctx(local
, curr_ctx
);
914 ieee80211_recalc_radar_chanctx(local
, curr_ctx
);
915 ieee80211_recalc_chanctx_min_def(local
, curr_ctx
, NULL
, false);
918 if (new_ctx
&& ieee80211_chanctx_num_assigned(local
, new_ctx
) > 0) {
919 ieee80211_recalc_txpower(link
, false);
920 ieee80211_recalc_chanctx_min_def(local
, new_ctx
, NULL
, false);
926 struct ieee80211_link_data
*tmp
;
929 for_each_sdata_link(local
, tmp
) {
930 if (rcu_access_pointer(tmp
->conf
->chanctx_conf
)) {
937 if (new_idle
!= sdata
->vif
.cfg
.idle
) {
938 sdata
->vif
.cfg
.idle
= new_idle
;
940 if (sdata
->vif
.type
!= NL80211_IFTYPE_P2P_DEVICE
&&
941 sdata
->vif
.type
!= NL80211_IFTYPE_MONITOR
)
942 ieee80211_vif_cfg_change_notify(sdata
, BSS_CHANGED_IDLE
);
945 ieee80211_check_fast_xmit_iface(sdata
);
950 void ieee80211_recalc_smps_chanctx(struct ieee80211_local
*local
,
951 struct ieee80211_chanctx
*chanctx
)
953 struct ieee80211_sub_if_data
*sdata
;
954 u8 rx_chains_static
, rx_chains_dynamic
;
955 struct ieee80211_link_data
*link
;
957 lockdep_assert_wiphy(local
->hw
.wiphy
);
959 rx_chains_static
= 1;
960 rx_chains_dynamic
= 1;
962 for_each_sdata_link(local
, link
) {
963 u8 needed_static
, needed_dynamic
;
965 switch (link
->sdata
->vif
.type
) {
966 case NL80211_IFTYPE_STATION
:
967 if (!link
->sdata
->u
.mgd
.associated
)
970 case NL80211_IFTYPE_MONITOR
:
971 if (!ieee80211_hw_check(&local
->hw
, NO_VIRTUAL_MONITOR
))
974 case NL80211_IFTYPE_AP
:
975 case NL80211_IFTYPE_ADHOC
:
976 case NL80211_IFTYPE_MESH_POINT
:
977 case NL80211_IFTYPE_OCB
:
983 if (rcu_access_pointer(link
->conf
->chanctx_conf
) != &chanctx
->conf
)
986 if (link
->sdata
->vif
.type
== NL80211_IFTYPE_MONITOR
) {
987 rx_chains_dynamic
= rx_chains_static
= local
->rx_chains
;
991 switch (link
->smps_mode
) {
993 WARN_ONCE(1, "Invalid SMPS mode %d\n",
996 case IEEE80211_SMPS_OFF
:
997 needed_static
= link
->needed_rx_chains
;
998 needed_dynamic
= link
->needed_rx_chains
;
1000 case IEEE80211_SMPS_DYNAMIC
:
1002 needed_dynamic
= link
->needed_rx_chains
;
1004 case IEEE80211_SMPS_STATIC
:
1010 rx_chains_static
= max(rx_chains_static
, needed_static
);
1011 rx_chains_dynamic
= max(rx_chains_dynamic
, needed_dynamic
);
1014 /* Disable SMPS for the monitor interface */
1015 sdata
= wiphy_dereference(local
->hw
.wiphy
, local
->monitor_sdata
);
1017 rcu_access_pointer(sdata
->vif
.bss_conf
.chanctx_conf
) == &chanctx
->conf
)
1018 rx_chains_dynamic
= rx_chains_static
= local
->rx_chains
;
1020 if (rx_chains_static
== chanctx
->conf
.rx_chains_static
&&
1021 rx_chains_dynamic
== chanctx
->conf
.rx_chains_dynamic
)
1024 chanctx
->conf
.rx_chains_static
= rx_chains_static
;
1025 chanctx
->conf
.rx_chains_dynamic
= rx_chains_dynamic
;
1026 drv_change_chanctx(local
, chanctx
, IEEE80211_CHANCTX_CHANGE_RX_CHAINS
);
1030 __ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data
*link
,
1033 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1034 unsigned int link_id
= link
->link_id
;
1035 struct ieee80211_bss_conf
*link_conf
= link
->conf
;
1036 struct ieee80211_local
*local __maybe_unused
= sdata
->local
;
1037 struct ieee80211_sub_if_data
*vlan
;
1038 struct ieee80211_chanctx_conf
*conf
;
1040 if (WARN_ON(sdata
->vif
.type
!= NL80211_IFTYPE_AP
))
1043 lockdep_assert_wiphy(local
->hw
.wiphy
);
1045 /* Check that conf exists, even when clearing this function
1046 * must be called with the AP's channel context still there
1047 * as it would otherwise cause VLANs to have an invalid
1048 * channel context pointer for a while, possibly pointing
1049 * to a channel context that has already been freed.
1051 conf
= rcu_dereference_protected(link_conf
->chanctx_conf
,
1052 lockdep_is_held(&local
->hw
.wiphy
->mtx
));
1058 list_for_each_entry(vlan
, &sdata
->u
.ap
.vlans
, u
.vlan
.list
) {
1059 struct ieee80211_bss_conf
*vlan_conf
;
1061 vlan_conf
= wiphy_dereference(local
->hw
.wiphy
,
1062 vlan
->vif
.link_conf
[link_id
]);
1063 if (WARN_ON(!vlan_conf
))
1066 rcu_assign_pointer(vlan_conf
->chanctx_conf
, conf
);
1070 void ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data
*link
,
1073 struct ieee80211_local
*local
= link
->sdata
->local
;
1075 lockdep_assert_wiphy(local
->hw
.wiphy
);
1077 __ieee80211_link_copy_chanctx_to_vlans(link
, clear
);
1080 int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data
*link
)
1082 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1083 struct ieee80211_chanctx
*ctx
= link
->reserved_chanctx
;
1085 lockdep_assert_wiphy(sdata
->local
->hw
.wiphy
);
1090 list_del(&link
->reserved_chanctx_list
);
1091 link
->reserved_chanctx
= NULL
;
1093 if (ieee80211_chanctx_refcount(sdata
->local
, ctx
) == 0) {
1094 if (ctx
->replace_state
== IEEE80211_CHANCTX_REPLACES_OTHER
) {
1095 if (WARN_ON(!ctx
->replace_ctx
))
1098 WARN_ON(ctx
->replace_ctx
->replace_state
!=
1099 IEEE80211_CHANCTX_WILL_BE_REPLACED
);
1100 WARN_ON(ctx
->replace_ctx
->replace_ctx
!= ctx
);
1102 ctx
->replace_ctx
->replace_ctx
= NULL
;
1103 ctx
->replace_ctx
->replace_state
=
1104 IEEE80211_CHANCTX_REPLACE_NONE
;
1106 list_del_rcu(&ctx
->list
);
1107 kfree_rcu(ctx
, rcu_head
);
1109 ieee80211_free_chanctx(sdata
->local
, ctx
, false);
1116 static struct ieee80211_chanctx
*
1117 ieee80211_replace_chanctx(struct ieee80211_local
*local
,
1118 const struct ieee80211_chan_req
*chanreq
,
1119 enum ieee80211_chanctx_mode mode
,
1120 struct ieee80211_chanctx
*curr_ctx
)
1122 struct ieee80211_chanctx
*new_ctx
, *ctx
;
1123 struct wiphy
*wiphy
= local
->hw
.wiphy
;
1124 const struct wiphy_radio
*radio
;
1126 if (!curr_ctx
|| (curr_ctx
->replace_state
==
1127 IEEE80211_CHANCTX_WILL_BE_REPLACED
) ||
1128 !list_empty(&curr_ctx
->reserved_links
)) {
1130 * Another link already requested this context for a
1131 * reservation. Find another one hoping all links assigned
1132 * to it will also switch soon enough.
1134 * TODO: This needs a little more work as some cases
1135 * (more than 2 chanctx capable devices) may fail which could
1136 * otherwise succeed provided some channel context juggling was
1139 * Consider ctx1..3, link1..6, each ctx has 2 links. link1 and
1140 * link2 from ctx1 request new different chandefs starting 2
1141 * in-place reservations with ctx4 and ctx5 replacing ctx1 and
1142 * ctx2 respectively. Next link5 and link6 from ctx3 reserve
1143 * ctx4. If link3 and link4 remain on ctx2 as they are then this
1144 * fails unless `replace_ctx` from ctx5 is replaced with ctx3.
1146 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
1147 if (ctx
->replace_state
!=
1148 IEEE80211_CHANCTX_REPLACE_NONE
)
1151 if (!list_empty(&ctx
->reserved_links
))
1154 if (ctx
->conf
.radio_idx
>= 0) {
1155 radio
= &wiphy
->radio
[ctx
->conf
.radio_idx
];
1156 if (!cfg80211_radio_chandef_valid(radio
, &chanreq
->oper
))
1166 * If that's true then all available contexts already have reservations
1167 * and cannot be used.
1169 if (!curr_ctx
|| (curr_ctx
->replace_state
==
1170 IEEE80211_CHANCTX_WILL_BE_REPLACED
) ||
1171 !list_empty(&curr_ctx
->reserved_links
))
1172 return ERR_PTR(-EBUSY
);
1174 new_ctx
= ieee80211_alloc_chanctx(local
, chanreq
, mode
, -1);
1176 return ERR_PTR(-ENOMEM
);
1178 new_ctx
->replace_ctx
= curr_ctx
;
1179 new_ctx
->replace_state
= IEEE80211_CHANCTX_REPLACES_OTHER
;
1181 curr_ctx
->replace_ctx
= new_ctx
;
1182 curr_ctx
->replace_state
= IEEE80211_CHANCTX_WILL_BE_REPLACED
;
1184 list_add_rcu(&new_ctx
->list
, &local
->chanctx_list
);
1190 ieee80211_find_available_radio(struct ieee80211_local
*local
,
1191 const struct ieee80211_chan_req
*chanreq
,
1192 u32 radio_mask
, int *radio_idx
)
1194 struct wiphy
*wiphy
= local
->hw
.wiphy
;
1195 const struct wiphy_radio
*radio
;
1199 if (!wiphy
->n_radio
)
1202 for (i
= 0; i
< wiphy
->n_radio
; i
++) {
1203 if (!(radio_mask
& BIT(i
)))
1206 radio
= &wiphy
->radio
[i
];
1207 if (!cfg80211_radio_chandef_valid(radio
, &chanreq
->oper
))
1210 if (!ieee80211_can_create_new_chanctx(local
, i
))
1220 int ieee80211_link_reserve_chanctx(struct ieee80211_link_data
*link
,
1221 const struct ieee80211_chan_req
*chanreq
,
1222 enum ieee80211_chanctx_mode mode
,
1223 bool radar_required
)
1225 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1226 struct ieee80211_local
*local
= sdata
->local
;
1227 struct ieee80211_chanctx
*new_ctx
, *curr_ctx
;
1230 lockdep_assert_wiphy(local
->hw
.wiphy
);
1232 curr_ctx
= ieee80211_link_get_chanctx(link
);
1233 if (curr_ctx
&& !local
->ops
->switch_vif_chanctx
)
1236 new_ctx
= ieee80211_find_reservation_chanctx(local
, chanreq
, mode
);
1238 if (ieee80211_can_create_new_chanctx(local
, -1) &&
1239 ieee80211_find_available_radio(local
, chanreq
,
1240 sdata
->wdev
.radio_mask
,
1242 new_ctx
= ieee80211_new_chanctx(local
, chanreq
, mode
,
1245 new_ctx
= ieee80211_replace_chanctx(local
, chanreq
,
1247 if (IS_ERR(new_ctx
))
1248 return PTR_ERR(new_ctx
);
1251 list_add(&link
->reserved_chanctx_list
, &new_ctx
->reserved_links
);
1252 link
->reserved_chanctx
= new_ctx
;
1253 link
->reserved
= *chanreq
;
1254 link
->reserved_radar_required
= radar_required
;
1255 link
->reserved_ready
= false;
1261 ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data
*link
)
1263 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1265 switch (sdata
->vif
.type
) {
1266 case NL80211_IFTYPE_ADHOC
:
1267 case NL80211_IFTYPE_AP
:
1268 case NL80211_IFTYPE_MESH_POINT
:
1269 case NL80211_IFTYPE_OCB
:
1270 wiphy_work_queue(sdata
->local
->hw
.wiphy
,
1271 &link
->csa
.finalize_work
);
1273 case NL80211_IFTYPE_STATION
:
1274 wiphy_delayed_work_queue(sdata
->local
->hw
.wiphy
,
1275 &link
->u
.mgd
.csa
.switch_work
, 0);
1277 case NL80211_IFTYPE_UNSPECIFIED
:
1278 case NL80211_IFTYPE_AP_VLAN
:
1279 case NL80211_IFTYPE_WDS
:
1280 case NL80211_IFTYPE_MONITOR
:
1281 case NL80211_IFTYPE_P2P_CLIENT
:
1282 case NL80211_IFTYPE_P2P_GO
:
1283 case NL80211_IFTYPE_P2P_DEVICE
:
1284 case NL80211_IFTYPE_NAN
:
1285 case NUM_NL80211_IFTYPES
:
1292 ieee80211_link_update_chanreq(struct ieee80211_link_data
*link
,
1293 const struct ieee80211_chan_req
*chanreq
)
1295 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1296 unsigned int link_id
= link
->link_id
;
1297 struct ieee80211_sub_if_data
*vlan
;
1299 link
->conf
->chanreq
= *chanreq
;
1301 if (sdata
->vif
.type
!= NL80211_IFTYPE_AP
)
1304 list_for_each_entry(vlan
, &sdata
->u
.ap
.vlans
, u
.vlan
.list
) {
1305 struct ieee80211_bss_conf
*vlan_conf
;
1307 vlan_conf
= wiphy_dereference(sdata
->local
->hw
.wiphy
,
1308 vlan
->vif
.link_conf
[link_id
]);
1309 if (WARN_ON(!vlan_conf
))
1312 vlan_conf
->chanreq
= *chanreq
;
1317 ieee80211_link_use_reserved_reassign(struct ieee80211_link_data
*link
)
1319 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1320 struct ieee80211_bss_conf
*link_conf
= link
->conf
;
1321 struct ieee80211_local
*local
= sdata
->local
;
1322 struct ieee80211_vif_chanctx_switch vif_chsw
[1] = {};
1323 struct ieee80211_chanctx
*old_ctx
, *new_ctx
;
1324 const struct ieee80211_chan_req
*chanreq
;
1325 struct ieee80211_chan_req tmp
;
1329 lockdep_assert_wiphy(local
->hw
.wiphy
);
1331 new_ctx
= link
->reserved_chanctx
;
1332 old_ctx
= ieee80211_link_get_chanctx(link
);
1334 if (WARN_ON(!link
->reserved_ready
))
1337 if (WARN_ON(!new_ctx
))
1340 if (WARN_ON(!old_ctx
))
1343 if (WARN_ON(new_ctx
->replace_state
==
1344 IEEE80211_CHANCTX_REPLACES_OTHER
))
1347 chanreq
= ieee80211_chanctx_non_reserved_chandef(local
, new_ctx
,
1350 if (WARN_ON(!chanreq
))
1353 if (link_conf
->chanreq
.oper
.width
!= link
->reserved
.oper
.width
)
1354 changed
= BSS_CHANGED_BANDWIDTH
;
1356 ieee80211_link_update_chanreq(link
, &link
->reserved
);
1358 _ieee80211_change_chanctx(local
, new_ctx
, old_ctx
, chanreq
, link
);
1360 vif_chsw
[0].vif
= &sdata
->vif
;
1361 vif_chsw
[0].old_ctx
= &old_ctx
->conf
;
1362 vif_chsw
[0].new_ctx
= &new_ctx
->conf
;
1363 vif_chsw
[0].link_conf
= link
->conf
;
1365 list_del(&link
->reserved_chanctx_list
);
1366 link
->reserved_chanctx
= NULL
;
1368 err
= drv_switch_vif_chanctx(local
, vif_chsw
, 1,
1369 CHANCTX_SWMODE_REASSIGN_VIF
);
1371 if (ieee80211_chanctx_refcount(local
, new_ctx
) == 0)
1372 ieee80211_free_chanctx(local
, new_ctx
, false);
1377 list_move(&link
->assigned_chanctx_list
, &new_ctx
->assigned_links
);
1378 rcu_assign_pointer(link_conf
->chanctx_conf
, &new_ctx
->conf
);
1380 if (sdata
->vif
.type
== NL80211_IFTYPE_AP
)
1381 __ieee80211_link_copy_chanctx_to_vlans(link
, false);
1383 ieee80211_check_fast_xmit_iface(sdata
);
1385 if (ieee80211_chanctx_refcount(local
, old_ctx
) == 0)
1386 ieee80211_free_chanctx(local
, old_ctx
, false);
1388 ieee80211_recalc_chanctx_min_def(local
, new_ctx
, NULL
, false);
1389 ieee80211_recalc_smps_chanctx(local
, new_ctx
);
1390 ieee80211_recalc_radar_chanctx(local
, new_ctx
);
1393 ieee80211_link_info_change_notify(sdata
, link
, changed
);
1396 ieee80211_link_chanctx_reservation_complete(link
);
1401 ieee80211_link_use_reserved_assign(struct ieee80211_link_data
*link
)
1403 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1404 struct ieee80211_local
*local
= sdata
->local
;
1405 struct ieee80211_chanctx
*old_ctx
, *new_ctx
;
1406 const struct ieee80211_chan_req
*chanreq
;
1407 struct ieee80211_chan_req tmp
;
1410 old_ctx
= ieee80211_link_get_chanctx(link
);
1411 new_ctx
= link
->reserved_chanctx
;
1413 if (WARN_ON(!link
->reserved_ready
))
1416 if (WARN_ON(old_ctx
))
1419 if (WARN_ON(!new_ctx
))
1422 if (WARN_ON(new_ctx
->replace_state
==
1423 IEEE80211_CHANCTX_REPLACES_OTHER
))
1426 chanreq
= ieee80211_chanctx_non_reserved_chandef(local
, new_ctx
,
1429 if (WARN_ON(!chanreq
))
1432 ieee80211_change_chanctx(local
, new_ctx
, new_ctx
, chanreq
);
1434 list_del(&link
->reserved_chanctx_list
);
1435 link
->reserved_chanctx
= NULL
;
1437 err
= ieee80211_assign_link_chanctx(link
, new_ctx
, false);
1439 if (ieee80211_chanctx_refcount(local
, new_ctx
) == 0)
1440 ieee80211_free_chanctx(local
, new_ctx
, false);
1446 ieee80211_link_chanctx_reservation_complete(link
);
1451 ieee80211_link_has_in_place_reservation(struct ieee80211_link_data
*link
)
1453 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1454 struct ieee80211_chanctx
*old_ctx
, *new_ctx
;
1456 lockdep_assert_wiphy(sdata
->local
->hw
.wiphy
);
1458 new_ctx
= link
->reserved_chanctx
;
1459 old_ctx
= ieee80211_link_get_chanctx(link
);
1464 if (WARN_ON(!new_ctx
))
1467 if (old_ctx
->replace_state
!= IEEE80211_CHANCTX_WILL_BE_REPLACED
)
1470 if (new_ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1476 static int ieee80211_chsw_switch_vifs(struct ieee80211_local
*local
,
1479 struct ieee80211_vif_chanctx_switch
*vif_chsw
;
1480 struct ieee80211_link_data
*link
;
1481 struct ieee80211_chanctx
*ctx
, *old_ctx
;
1484 lockdep_assert_wiphy(local
->hw
.wiphy
);
1486 vif_chsw
= kcalloc(n_vifs
, sizeof(vif_chsw
[0]), GFP_KERNEL
);
1491 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
1492 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1495 if (WARN_ON(!ctx
->replace_ctx
)) {
1500 list_for_each_entry(link
, &ctx
->reserved_links
,
1501 reserved_chanctx_list
) {
1502 if (!ieee80211_link_has_in_place_reservation(link
))
1505 old_ctx
= ieee80211_link_get_chanctx(link
);
1506 vif_chsw
[i
].vif
= &link
->sdata
->vif
;
1507 vif_chsw
[i
].old_ctx
= &old_ctx
->conf
;
1508 vif_chsw
[i
].new_ctx
= &ctx
->conf
;
1509 vif_chsw
[i
].link_conf
= link
->conf
;
1515 err
= drv_switch_vif_chanctx(local
, vif_chsw
, n_vifs
,
1516 CHANCTX_SWMODE_SWAP_CONTEXTS
);
1523 static int ieee80211_chsw_switch_ctxs(struct ieee80211_local
*local
)
1525 struct ieee80211_chanctx
*ctx
;
1528 lockdep_assert_wiphy(local
->hw
.wiphy
);
1530 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
1531 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1534 if (!list_empty(&ctx
->replace_ctx
->assigned_links
))
1537 ieee80211_del_chanctx(local
, ctx
->replace_ctx
, false);
1538 err
= ieee80211_add_chanctx(local
, ctx
);
1546 WARN_ON(ieee80211_add_chanctx(local
, ctx
));
1547 list_for_each_entry_continue_reverse(ctx
, &local
->chanctx_list
, list
) {
1548 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1551 if (!list_empty(&ctx
->replace_ctx
->assigned_links
))
1554 ieee80211_del_chanctx(local
, ctx
, false);
1555 WARN_ON(ieee80211_add_chanctx(local
, ctx
->replace_ctx
));
1561 static int ieee80211_vif_use_reserved_switch(struct ieee80211_local
*local
)
1563 struct ieee80211_chanctx
*ctx
, *ctx_tmp
, *old_ctx
;
1564 int err
, n_assigned
, n_reserved
, n_ready
;
1565 int n_ctx
= 0, n_vifs_switch
= 0, n_vifs_assign
= 0, n_vifs_ctxless
= 0;
1567 lockdep_assert_wiphy(local
->hw
.wiphy
);
1570 * If there are 2 independent pairs of channel contexts performing
1571 * cross-switch of their vifs this code will still wait until both are
1572 * ready even though it could be possible to switch one before the
1575 * For practical reasons and code simplicity just do a single huge
1580 * Verify if the reservation is still feasible.
1581 * - if it's not then disconnect
1582 * - if it is but not all vifs necessary are ready then defer
1585 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
1586 struct ieee80211_link_data
*link
;
1588 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1591 if (WARN_ON(!ctx
->replace_ctx
)) {
1602 list_for_each_entry(link
, &ctx
->replace_ctx
->assigned_links
,
1603 assigned_chanctx_list
) {
1605 if (link
->reserved_chanctx
) {
1607 if (link
->reserved_ready
)
1612 if (n_assigned
!= n_reserved
) {
1613 if (n_ready
== n_reserved
) {
1614 wiphy_info(local
->hw
.wiphy
,
1615 "channel context reservation cannot be finalized because some interfaces aren't switching\n");
1623 ctx
->conf
.radar_enabled
= false;
1624 list_for_each_entry(link
, &ctx
->reserved_links
,
1625 reserved_chanctx_list
) {
1626 if (ieee80211_link_has_in_place_reservation(link
) &&
1627 !link
->reserved_ready
)
1630 old_ctx
= ieee80211_link_get_chanctx(link
);
1632 if (old_ctx
->replace_state
==
1633 IEEE80211_CHANCTX_WILL_BE_REPLACED
)
1641 if (link
->reserved_radar_required
)
1642 ctx
->conf
.radar_enabled
= true;
1646 if (WARN_ON(n_ctx
== 0) ||
1647 WARN_ON(n_vifs_switch
== 0 &&
1648 n_vifs_assign
== 0 &&
1649 n_vifs_ctxless
== 0)) {
1654 /* update station rate control and min width before switch */
1655 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
1656 struct ieee80211_link_data
*link
;
1658 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1661 if (WARN_ON(!ctx
->replace_ctx
)) {
1666 list_for_each_entry(link
, &ctx
->reserved_links
,
1667 reserved_chanctx_list
) {
1668 if (!ieee80211_link_has_in_place_reservation(link
))
1671 ieee80211_chan_bw_change(local
,
1672 ieee80211_link_get_chanctx(link
),
1676 ieee80211_recalc_chanctx_min_def(local
, ctx
, NULL
, true);
1680 * All necessary vifs are ready. Perform the switch now depending on
1681 * reservations and driver capabilities.
1684 if (n_vifs_switch
> 0) {
1685 err
= ieee80211_chsw_switch_vifs(local
, n_vifs_switch
);
1690 if (n_vifs_assign
> 0 || n_vifs_ctxless
> 0) {
1691 err
= ieee80211_chsw_switch_ctxs(local
);
1697 * Update all structures, values and pointers to point to new channel
1700 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
1701 struct ieee80211_link_data
*link
, *link_tmp
;
1703 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1706 if (WARN_ON(!ctx
->replace_ctx
)) {
1711 list_for_each_entry(link
, &ctx
->reserved_links
,
1712 reserved_chanctx_list
) {
1713 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1714 struct ieee80211_bss_conf
*link_conf
= link
->conf
;
1717 if (!ieee80211_link_has_in_place_reservation(link
))
1720 rcu_assign_pointer(link_conf
->chanctx_conf
,
1723 if (sdata
->vif
.type
== NL80211_IFTYPE_AP
)
1724 __ieee80211_link_copy_chanctx_to_vlans(link
,
1727 ieee80211_check_fast_xmit_iface(sdata
);
1729 link
->radar_required
= link
->reserved_radar_required
;
1731 if (link_conf
->chanreq
.oper
.width
!= link
->reserved
.oper
.width
)
1732 changed
= BSS_CHANGED_BANDWIDTH
;
1734 ieee80211_link_update_chanreq(link
, &link
->reserved
);
1736 ieee80211_link_info_change_notify(sdata
,
1740 ieee80211_recalc_txpower(link
, false);
1743 ieee80211_recalc_chanctx_chantype(local
, ctx
);
1744 ieee80211_recalc_smps_chanctx(local
, ctx
);
1745 ieee80211_recalc_radar_chanctx(local
, ctx
);
1746 ieee80211_recalc_chanctx_min_def(local
, ctx
, NULL
, false);
1748 list_for_each_entry_safe(link
, link_tmp
, &ctx
->reserved_links
,
1749 reserved_chanctx_list
) {
1750 if (ieee80211_link_get_chanctx(link
) != ctx
)
1753 list_del(&link
->reserved_chanctx_list
);
1754 list_move(&link
->assigned_chanctx_list
,
1755 &ctx
->assigned_links
);
1756 link
->reserved_chanctx
= NULL
;
1758 ieee80211_link_chanctx_reservation_complete(link
);
1759 ieee80211_chan_bw_change(local
, ctx
, false, false);
1763 * This context might have been a dependency for an already
1764 * ready re-assign reservation interface that was deferred. Do
1765 * not propagate error to the caller though. The in-place
1766 * reservation for originally requested interface has already
1767 * succeeded at this point.
1769 list_for_each_entry_safe(link
, link_tmp
, &ctx
->reserved_links
,
1770 reserved_chanctx_list
) {
1771 if (WARN_ON(ieee80211_link_has_in_place_reservation(link
)))
1774 if (WARN_ON(link
->reserved_chanctx
!= ctx
))
1777 if (!link
->reserved_ready
)
1780 if (ieee80211_link_get_chanctx(link
))
1781 err
= ieee80211_link_use_reserved_reassign(link
);
1783 err
= ieee80211_link_use_reserved_assign(link
);
1787 "failed to finalize (re-)assign reservation (err=%d)\n",
1789 ieee80211_link_unreserve_chanctx(link
);
1790 cfg80211_stop_iface(local
->hw
.wiphy
,
1798 * Finally free old contexts
1801 list_for_each_entry_safe(ctx
, ctx_tmp
, &local
->chanctx_list
, list
) {
1802 if (ctx
->replace_state
!= IEEE80211_CHANCTX_WILL_BE_REPLACED
)
1805 ctx
->replace_ctx
->replace_ctx
= NULL
;
1806 ctx
->replace_ctx
->replace_state
=
1807 IEEE80211_CHANCTX_REPLACE_NONE
;
1809 list_del_rcu(&ctx
->list
);
1810 kfree_rcu(ctx
, rcu_head
);
1816 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
1817 struct ieee80211_link_data
*link
, *link_tmp
;
1819 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1822 list_for_each_entry_safe(link
, link_tmp
, &ctx
->reserved_links
,
1823 reserved_chanctx_list
) {
1824 ieee80211_link_unreserve_chanctx(link
);
1825 ieee80211_link_chanctx_reservation_complete(link
);
1832 void __ieee80211_link_release_channel(struct ieee80211_link_data
*link
,
1833 bool skip_idle_recalc
)
1835 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1836 struct ieee80211_bss_conf
*link_conf
= link
->conf
;
1837 struct ieee80211_local
*local
= sdata
->local
;
1838 struct ieee80211_chanctx_conf
*conf
;
1839 struct ieee80211_chanctx
*ctx
;
1840 bool use_reserved_switch
= false;
1842 lockdep_assert_wiphy(local
->hw
.wiphy
);
1844 conf
= rcu_dereference_protected(link_conf
->chanctx_conf
,
1845 lockdep_is_held(&local
->hw
.wiphy
->mtx
));
1849 ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
1851 if (link
->reserved_chanctx
) {
1852 if (link
->reserved_chanctx
->replace_state
== IEEE80211_CHANCTX_REPLACES_OTHER
&&
1853 ieee80211_chanctx_num_reserved(local
, link
->reserved_chanctx
) > 1)
1854 use_reserved_switch
= true;
1856 ieee80211_link_unreserve_chanctx(link
);
1859 ieee80211_assign_link_chanctx(link
, NULL
, false);
1860 if (ieee80211_chanctx_refcount(local
, ctx
) == 0)
1861 ieee80211_free_chanctx(local
, ctx
, skip_idle_recalc
);
1863 link
->radar_required
= false;
1865 /* Unreserving may ready an in-place reservation. */
1866 if (use_reserved_switch
)
1867 ieee80211_vif_use_reserved_switch(local
);
1870 int _ieee80211_link_use_channel(struct ieee80211_link_data
*link
,
1871 const struct ieee80211_chan_req
*chanreq
,
1872 enum ieee80211_chanctx_mode mode
,
1873 bool assign_on_failure
)
1875 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1876 struct ieee80211_local
*local
= sdata
->local
;
1877 struct ieee80211_chanctx
*ctx
;
1878 u8 radar_detect_width
= 0;
1879 bool reserved
= false;
1883 lockdep_assert_wiphy(local
->hw
.wiphy
);
1885 if (!ieee80211_vif_link_active(&sdata
->vif
, link
->link_id
)) {
1886 ieee80211_link_update_chanreq(link
, chanreq
);
1890 ret
= cfg80211_chandef_dfs_required(local
->hw
.wiphy
,
1892 sdata
->wdev
.iftype
);
1896 radar_detect_width
= BIT(chanreq
->oper
.width
);
1898 link
->radar_required
= ret
;
1900 ret
= ieee80211_check_combinations(sdata
, &chanreq
->oper
, mode
,
1901 radar_detect_width
, -1);
1905 __ieee80211_link_release_channel(link
, false);
1907 ctx
= ieee80211_find_chanctx(local
, link
, chanreq
, mode
);
1908 /* Note: context is now reserved */
1911 else if (!ieee80211_find_available_radio(local
, chanreq
,
1912 sdata
->wdev
.radio_mask
,
1914 ctx
= ERR_PTR(-EBUSY
);
1916 ctx
= ieee80211_new_chanctx(local
, chanreq
, mode
,
1917 assign_on_failure
, radio_idx
);
1923 ieee80211_link_update_chanreq(link
, chanreq
);
1925 ret
= ieee80211_assign_link_chanctx(link
, ctx
, assign_on_failure
);
1928 /* remove reservation */
1929 WARN_ON(link
->reserved_chanctx
!= ctx
);
1930 link
->reserved_chanctx
= NULL
;
1931 list_del(&link
->reserved_chanctx_list
);
1935 /* if assign fails refcount stays the same */
1936 if (ieee80211_chanctx_refcount(local
, ctx
) == 0)
1937 ieee80211_free_chanctx(local
, ctx
, false);
1941 ieee80211_recalc_smps_chanctx(local
, ctx
);
1942 ieee80211_recalc_radar_chanctx(local
, ctx
);
1945 link
->radar_required
= false;
1950 int ieee80211_link_use_reserved_context(struct ieee80211_link_data
*link
)
1952 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1953 struct ieee80211_local
*local
= sdata
->local
;
1954 struct ieee80211_chanctx
*new_ctx
;
1955 struct ieee80211_chanctx
*old_ctx
;
1958 lockdep_assert_wiphy(local
->hw
.wiphy
);
1960 new_ctx
= link
->reserved_chanctx
;
1961 old_ctx
= ieee80211_link_get_chanctx(link
);
1963 if (WARN_ON(!new_ctx
))
1966 if (WARN_ON(new_ctx
->replace_state
==
1967 IEEE80211_CHANCTX_WILL_BE_REPLACED
))
1970 if (WARN_ON(link
->reserved_ready
))
1973 link
->reserved_ready
= true;
1975 if (new_ctx
->replace_state
== IEEE80211_CHANCTX_REPLACE_NONE
) {
1977 return ieee80211_link_use_reserved_reassign(link
);
1979 return ieee80211_link_use_reserved_assign(link
);
1983 * In-place reservation may need to be finalized now either if:
1984 * a) sdata is taking part in the swapping itself and is the last one
1985 * b) sdata has switched with a re-assign reservation to an existing
1986 * context readying in-place switching of old_ctx
1988 * In case of (b) do not propagate the error up because the requested
1989 * sdata already switched successfully. Just spill an extra warning.
1990 * The ieee80211_vif_use_reserved_switch() already stops all necessary
1991 * interfaces upon failure.
1994 old_ctx
->replace_state
== IEEE80211_CHANCTX_WILL_BE_REPLACED
) ||
1995 new_ctx
->replace_state
== IEEE80211_CHANCTX_REPLACES_OTHER
) {
1996 err
= ieee80211_vif_use_reserved_switch(local
);
1997 if (err
&& err
!= -EAGAIN
) {
1998 if (new_ctx
->replace_state
==
1999 IEEE80211_CHANCTX_REPLACES_OTHER
)
2002 wiphy_info(local
->hw
.wiphy
,
2003 "depending in-place reservation failed (err=%d)\n",
2012 * This is similar to ieee80211_chanctx_compatible(), but rechecks
2013 * against all the links actually using it (except the one that's
2014 * passed, since that one is changing).
2015 * This is done in order to allow changes to the AP's bandwidth for
2016 * wider bandwidth OFDMA purposes, which wouldn't be treated as
2017 * compatible by ieee80211_chanctx_recheck() but is OK if the link
2018 * requesting the update is the only one using it.
2020 static const struct ieee80211_chan_req
*
2021 ieee80211_chanctx_recheck(struct ieee80211_local
*local
,
2022 struct ieee80211_link_data
*skip_link
,
2023 struct ieee80211_chanctx
*ctx
,
2024 const struct ieee80211_chan_req
*req
,
2025 struct ieee80211_chan_req
*tmp
)
2027 const struct ieee80211_chan_req
*ret
= req
;
2028 struct ieee80211_link_data
*link
;
2030 lockdep_assert_wiphy(local
->hw
.wiphy
);
2032 for_each_sdata_link(local
, link
) {
2033 if (link
== skip_link
)
2036 if (rcu_access_pointer(link
->conf
->chanctx_conf
) == &ctx
->conf
) {
2037 ret
= ieee80211_chanreq_compatible(ret
,
2038 &link
->conf
->chanreq
,
2044 if (link
->reserved_chanctx
== ctx
) {
2045 ret
= ieee80211_chanreq_compatible(ret
,
2057 int ieee80211_link_change_chanreq(struct ieee80211_link_data
*link
,
2058 const struct ieee80211_chan_req
*chanreq
,
2061 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
2062 struct ieee80211_bss_conf
*link_conf
= link
->conf
;
2063 struct ieee80211_local
*local
= sdata
->local
;
2064 struct ieee80211_chanctx_conf
*conf
;
2065 struct ieee80211_chanctx
*ctx
;
2066 const struct ieee80211_chan_req
*compat
;
2067 struct ieee80211_chan_req tmp
;
2069 lockdep_assert_wiphy(local
->hw
.wiphy
);
2071 if (!cfg80211_chandef_usable(sdata
->local
->hw
.wiphy
,
2073 IEEE80211_CHAN_DISABLED
))
2076 /* for non-HT 20 MHz the rest doesn't matter */
2077 if (chanreq
->oper
.width
== NL80211_CHAN_WIDTH_20_NOHT
&&
2078 cfg80211_chandef_identical(&chanreq
->oper
, &link_conf
->chanreq
.oper
))
2081 /* but you cannot switch to/from it */
2082 if (chanreq
->oper
.width
== NL80211_CHAN_WIDTH_20_NOHT
||
2083 link_conf
->chanreq
.oper
.width
== NL80211_CHAN_WIDTH_20_NOHT
)
2086 conf
= rcu_dereference_protected(link_conf
->chanctx_conf
,
2087 lockdep_is_held(&local
->hw
.wiphy
->mtx
));
2091 ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
2093 compat
= ieee80211_chanctx_recheck(local
, link
, ctx
, chanreq
, &tmp
);
2097 switch (ctx
->replace_state
) {
2098 case IEEE80211_CHANCTX_REPLACE_NONE
:
2099 if (!ieee80211_chanctx_reserved_chanreq(local
, ctx
, compat
,
2103 case IEEE80211_CHANCTX_WILL_BE_REPLACED
:
2104 /* TODO: Perhaps the bandwidth change could be treated as a
2105 * reservation itself? */
2107 case IEEE80211_CHANCTX_REPLACES_OTHER
:
2108 /* channel context that is going to replace another channel
2109 * context doesn't really exist and shouldn't be assigned
2115 ieee80211_link_update_chanreq(link
, chanreq
);
2117 ieee80211_recalc_chanctx_chantype(local
, ctx
);
2119 *changed
|= BSS_CHANGED_BANDWIDTH
;
2123 void ieee80211_link_release_channel(struct ieee80211_link_data
*link
)
2125 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
2127 lockdep_assert_wiphy(sdata
->local
->hw
.wiphy
);
2129 if (rcu_access_pointer(link
->conf
->chanctx_conf
))
2130 __ieee80211_link_release_channel(link
, false);
2133 void ieee80211_link_vlan_copy_chanctx(struct ieee80211_link_data
*link
)
2135 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
2136 unsigned int link_id
= link
->link_id
;
2137 struct ieee80211_bss_conf
*link_conf
= link
->conf
;
2138 struct ieee80211_bss_conf
*ap_conf
;
2139 struct ieee80211_local
*local
= sdata
->local
;
2140 struct ieee80211_sub_if_data
*ap
;
2141 struct ieee80211_chanctx_conf
*conf
;
2143 lockdep_assert_wiphy(local
->hw
.wiphy
);
2145 if (WARN_ON(sdata
->vif
.type
!= NL80211_IFTYPE_AP_VLAN
|| !sdata
->bss
))
2148 ap
= container_of(sdata
->bss
, struct ieee80211_sub_if_data
, u
.ap
);
2150 ap_conf
= wiphy_dereference(local
->hw
.wiphy
,
2151 ap
->vif
.link_conf
[link_id
]);
2152 conf
= wiphy_dereference(local
->hw
.wiphy
,
2153 ap_conf
->chanctx_conf
);
2154 rcu_assign_pointer(link_conf
->chanctx_conf
, conf
);
2157 void ieee80211_iter_chan_contexts_atomic(
2158 struct ieee80211_hw
*hw
,
2159 void (*iter
)(struct ieee80211_hw
*hw
,
2160 struct ieee80211_chanctx_conf
*chanctx_conf
,
2164 struct ieee80211_local
*local
= hw_to_local(hw
);
2165 struct ieee80211_chanctx
*ctx
;
2168 list_for_each_entry_rcu(ctx
, &local
->chanctx_list
, list
)
2169 if (ctx
->driver_present
)
2170 iter(hw
, &ctx
->conf
, iter_data
);
2173 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic
);