1 // SPDX-License-Identifier: GPL-2.0-only
3 * mac80211 - channel management
4 * Copyright 2020 - 2022 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
)
52 struct ieee80211_chanctx
*ctx
;
55 lockdep_assert_wiphy(local
->hw
.wiphy
);
57 list_for_each_entry(ctx
, &local
->chanctx_list
, list
)
63 static bool ieee80211_can_create_new_chanctx(struct ieee80211_local
*local
)
65 lockdep_assert_wiphy(local
->hw
.wiphy
);
67 return ieee80211_num_chanctx(local
) < ieee80211_max_num_channels(local
);
70 static struct ieee80211_chanctx
*
71 ieee80211_link_get_chanctx(struct ieee80211_link_data
*link
)
73 struct ieee80211_local
*local __maybe_unused
= link
->sdata
->local
;
74 struct ieee80211_chanctx_conf
*conf
;
76 conf
= rcu_dereference_protected(link
->conf
->chanctx_conf
,
77 lockdep_is_held(&local
->hw
.wiphy
->mtx
));
81 return container_of(conf
, struct ieee80211_chanctx
, conf
);
84 static const struct cfg80211_chan_def
*
85 ieee80211_chanctx_reserved_chandef(struct ieee80211_local
*local
,
86 struct ieee80211_chanctx
*ctx
,
87 const struct cfg80211_chan_def
*compat
)
89 struct ieee80211_link_data
*link
;
91 lockdep_assert_wiphy(local
->hw
.wiphy
);
93 list_for_each_entry(link
, &ctx
->reserved_links
,
94 reserved_chanctx_list
) {
96 compat
= &link
->reserved_chandef
;
98 compat
= cfg80211_chandef_compatible(&link
->reserved_chandef
,
107 static const struct cfg80211_chan_def
*
108 ieee80211_chanctx_non_reserved_chandef(struct ieee80211_local
*local
,
109 struct ieee80211_chanctx
*ctx
,
110 const struct cfg80211_chan_def
*compat
)
112 struct ieee80211_link_data
*link
;
114 lockdep_assert_wiphy(local
->hw
.wiphy
);
116 list_for_each_entry(link
, &ctx
->assigned_links
,
117 assigned_chanctx_list
) {
118 struct ieee80211_bss_conf
*link_conf
= link
->conf
;
120 if (link
->reserved_chanctx
)
124 compat
= &link_conf
->chandef
;
126 compat
= cfg80211_chandef_compatible(
127 &link_conf
->chandef
, compat
);
135 static const struct cfg80211_chan_def
*
136 ieee80211_chanctx_combined_chandef(struct ieee80211_local
*local
,
137 struct ieee80211_chanctx
*ctx
,
138 const struct cfg80211_chan_def
*compat
)
140 lockdep_assert_wiphy(local
->hw
.wiphy
);
142 compat
= ieee80211_chanctx_reserved_chandef(local
, ctx
, compat
);
146 compat
= ieee80211_chanctx_non_reserved_chandef(local
, ctx
, compat
);
154 ieee80211_chanctx_can_reserve_chandef(struct ieee80211_local
*local
,
155 struct ieee80211_chanctx
*ctx
,
156 const struct cfg80211_chan_def
*def
)
158 lockdep_assert_wiphy(local
->hw
.wiphy
);
160 if (ieee80211_chanctx_combined_chandef(local
, ctx
, def
))
163 if (!list_empty(&ctx
->reserved_links
) &&
164 ieee80211_chanctx_reserved_chandef(local
, ctx
, def
))
170 static struct ieee80211_chanctx
*
171 ieee80211_find_reservation_chanctx(struct ieee80211_local
*local
,
172 const struct cfg80211_chan_def
*chandef
,
173 enum ieee80211_chanctx_mode mode
)
175 struct ieee80211_chanctx
*ctx
;
177 lockdep_assert_wiphy(local
->hw
.wiphy
);
179 if (mode
== IEEE80211_CHANCTX_EXCLUSIVE
)
182 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
183 if (ctx
->replace_state
== IEEE80211_CHANCTX_WILL_BE_REPLACED
)
186 if (ctx
->mode
== IEEE80211_CHANCTX_EXCLUSIVE
)
189 if (!ieee80211_chanctx_can_reserve_chandef(local
, ctx
,
199 static enum nl80211_chan_width
ieee80211_get_sta_bw(struct sta_info
*sta
,
200 unsigned int link_id
)
202 enum ieee80211_sta_rx_bandwidth width
;
203 struct link_sta_info
*link_sta
;
205 link_sta
= rcu_dereference(sta
->link
[link_id
]);
207 /* no effect if this STA has no presence on this link */
209 return NL80211_CHAN_WIDTH_20_NOHT
;
211 width
= ieee80211_sta_cap_rx_bw(link_sta
);
214 case IEEE80211_STA_RX_BW_20
:
215 if (link_sta
->pub
->ht_cap
.ht_supported
)
216 return NL80211_CHAN_WIDTH_20
;
218 return NL80211_CHAN_WIDTH_20_NOHT
;
219 case IEEE80211_STA_RX_BW_40
:
220 return NL80211_CHAN_WIDTH_40
;
221 case IEEE80211_STA_RX_BW_80
:
222 return NL80211_CHAN_WIDTH_80
;
223 case IEEE80211_STA_RX_BW_160
:
225 * This applied for both 160 and 80+80. since we use
226 * the returned value to consider degradation of
227 * ctx->conf.min_def, we have to make sure to take
228 * the bigger one (NL80211_CHAN_WIDTH_160).
229 * Otherwise we might try degrading even when not
230 * needed, as the max required sta_bw returned (80+80)
231 * might be smaller than the configured bw (160).
233 return NL80211_CHAN_WIDTH_160
;
234 case IEEE80211_STA_RX_BW_320
:
235 return NL80211_CHAN_WIDTH_320
;
238 return NL80211_CHAN_WIDTH_20
;
242 static enum nl80211_chan_width
243 ieee80211_get_max_required_bw(struct ieee80211_sub_if_data
*sdata
,
244 unsigned int link_id
)
246 enum nl80211_chan_width max_bw
= NL80211_CHAN_WIDTH_20_NOHT
;
247 struct sta_info
*sta
;
249 list_for_each_entry_rcu(sta
, &sdata
->local
->sta_list
, list
) {
250 if (sdata
!= sta
->sdata
&&
251 !(sta
->sdata
->bss
&& sta
->sdata
->bss
== sdata
->bss
))
254 max_bw
= max(max_bw
, ieee80211_get_sta_bw(sta
, link_id
));
260 static enum nl80211_chan_width
261 ieee80211_get_chanctx_vif_max_required_bw(struct ieee80211_sub_if_data
*sdata
,
262 struct ieee80211_chanctx
*ctx
,
263 struct ieee80211_link_data
*rsvd_for
)
265 enum nl80211_chan_width max_bw
= NL80211_CHAN_WIDTH_20_NOHT
;
266 struct ieee80211_vif
*vif
= &sdata
->vif
;
270 for (link_id
= 0; link_id
< ARRAY_SIZE(sdata
->link
); link_id
++) {
271 enum nl80211_chan_width width
= NL80211_CHAN_WIDTH_20_NOHT
;
272 struct ieee80211_link_data
*link
=
273 rcu_dereference(sdata
->link
[link_id
]);
278 if (link
!= rsvd_for
&&
279 rcu_access_pointer(link
->conf
->chanctx_conf
) != &ctx
->conf
)
283 case NL80211_IFTYPE_AP
:
284 case NL80211_IFTYPE_AP_VLAN
:
285 width
= ieee80211_get_max_required_bw(sdata
, link_id
);
287 case NL80211_IFTYPE_STATION
:
289 * The ap's sta->bandwidth is not set yet at this
290 * point, so take the width from the chandef, but
291 * account also for TDLS peers
293 width
= max(link
->conf
->chandef
.width
,
294 ieee80211_get_max_required_bw(sdata
, link_id
));
296 case NL80211_IFTYPE_P2P_DEVICE
:
297 case NL80211_IFTYPE_NAN
:
299 case NL80211_IFTYPE_ADHOC
:
300 case NL80211_IFTYPE_MESH_POINT
:
301 case NL80211_IFTYPE_OCB
:
302 width
= link
->conf
->chandef
.width
;
304 case NL80211_IFTYPE_WDS
:
305 case NL80211_IFTYPE_UNSPECIFIED
:
306 case NUM_NL80211_IFTYPES
:
307 case NL80211_IFTYPE_MONITOR
:
308 case NL80211_IFTYPE_P2P_CLIENT
:
309 case NL80211_IFTYPE_P2P_GO
:
313 max_bw
= max(max_bw
, width
);
320 static enum nl80211_chan_width
321 ieee80211_get_chanctx_max_required_bw(struct ieee80211_local
*local
,
322 struct ieee80211_chanctx
*ctx
,
323 struct ieee80211_link_data
*rsvd_for
)
325 struct ieee80211_sub_if_data
*sdata
;
326 enum nl80211_chan_width max_bw
= NL80211_CHAN_WIDTH_20_NOHT
;
329 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
330 enum nl80211_chan_width width
;
332 if (!ieee80211_sdata_running(sdata
))
335 width
= ieee80211_get_chanctx_vif_max_required_bw(sdata
, ctx
,
338 max_bw
= max(max_bw
, width
);
341 /* use the configured bandwidth in case of monitor interface */
342 sdata
= rcu_dereference(local
->monitor_sdata
);
344 rcu_access_pointer(sdata
->vif
.bss_conf
.chanctx_conf
) == &ctx
->conf
)
345 max_bw
= max(max_bw
, ctx
->conf
.def
.width
);
353 * recalc the min required chan width of the channel context, which is
354 * the max of min required widths of all the interfaces bound to this
358 _ieee80211_recalc_chanctx_min_def(struct ieee80211_local
*local
,
359 struct ieee80211_chanctx
*ctx
,
360 struct ieee80211_link_data
*rsvd_for
)
362 enum nl80211_chan_width max_bw
;
363 struct cfg80211_chan_def min_def
;
365 lockdep_assert_wiphy(local
->hw
.wiphy
);
367 /* don't optimize non-20MHz based and radar_enabled confs */
368 if (ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_5
||
369 ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_10
||
370 ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_1
||
371 ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_2
||
372 ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_4
||
373 ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_8
||
374 ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_16
||
375 ctx
->conf
.radar_enabled
) {
376 ctx
->conf
.min_def
= ctx
->conf
.def
;
380 max_bw
= ieee80211_get_chanctx_max_required_bw(local
, ctx
, rsvd_for
);
382 /* downgrade chandef up to max_bw */
383 min_def
= ctx
->conf
.def
;
384 while (min_def
.width
> max_bw
)
385 ieee80211_chandef_downgrade(&min_def
);
387 if (cfg80211_chandef_identical(&ctx
->conf
.min_def
, &min_def
))
390 ctx
->conf
.min_def
= min_def
;
391 if (!ctx
->driver_present
)
394 return IEEE80211_CHANCTX_CHANGE_MIN_WIDTH
;
397 /* calling this function is assuming that station vif is updated to
398 * lates changes by calling ieee80211_link_update_chandef
400 static void ieee80211_chan_bw_change(struct ieee80211_local
*local
,
401 struct ieee80211_chanctx
*ctx
,
404 struct sta_info
*sta
;
405 struct ieee80211_supported_band
*sband
=
406 local
->hw
.wiphy
->bands
[ctx
->conf
.def
.chan
->band
];
409 list_for_each_entry_rcu(sta
, &local
->sta_list
,
411 struct ieee80211_sub_if_data
*sdata
= sta
->sdata
;
412 enum ieee80211_sta_rx_bandwidth new_sta_bw
;
413 unsigned int link_id
;
415 if (!ieee80211_sdata_running(sta
->sdata
))
418 for (link_id
= 0; link_id
< ARRAY_SIZE(sta
->sdata
->link
); link_id
++) {
419 struct ieee80211_bss_conf
*link_conf
=
420 rcu_dereference(sdata
->vif
.link_conf
[link_id
]);
421 struct link_sta_info
*link_sta
;
426 if (rcu_access_pointer(link_conf
->chanctx_conf
) != &ctx
->conf
)
429 link_sta
= rcu_dereference(sta
->link
[link_id
]);
433 new_sta_bw
= ieee80211_sta_cur_vht_bw(link_sta
);
436 if (new_sta_bw
== link_sta
->pub
->bandwidth
)
439 /* vif changed to narrow BW and narrow BW for station wasn't
440 * requested or vise versa */
441 if ((new_sta_bw
< link_sta
->pub
->bandwidth
) == !narrowed
)
444 link_sta
->pub
->bandwidth
= new_sta_bw
;
445 rate_control_rate_update(local
, sband
, sta
, link_id
,
446 IEEE80211_RC_BW_CHANGED
);
453 * recalc the min required chan width of the channel context, which is
454 * the max of min required widths of all the interfaces bound to this
457 void ieee80211_recalc_chanctx_min_def(struct ieee80211_local
*local
,
458 struct ieee80211_chanctx
*ctx
,
459 struct ieee80211_link_data
*rsvd_for
)
461 u32 changed
= _ieee80211_recalc_chanctx_min_def(local
, ctx
, rsvd_for
);
466 /* check is BW narrowed */
467 ieee80211_chan_bw_change(local
, ctx
, true);
469 drv_change_chanctx(local
, ctx
, changed
);
471 /* check is BW wider */
472 ieee80211_chan_bw_change(local
, ctx
, false);
475 static void _ieee80211_change_chanctx(struct ieee80211_local
*local
,
476 struct ieee80211_chanctx
*ctx
,
477 struct ieee80211_chanctx
*old_ctx
,
478 const struct cfg80211_chan_def
*chandef
,
479 struct ieee80211_link_data
*rsvd_for
)
483 /* expected to handle only 20/40/80/160/320 channel widths */
484 switch (chandef
->width
) {
485 case NL80211_CHAN_WIDTH_20_NOHT
:
486 case NL80211_CHAN_WIDTH_20
:
487 case NL80211_CHAN_WIDTH_40
:
488 case NL80211_CHAN_WIDTH_80
:
489 case NL80211_CHAN_WIDTH_80P80
:
490 case NL80211_CHAN_WIDTH_160
:
491 case NL80211_CHAN_WIDTH_320
:
497 /* Check maybe BW narrowed - we do this _before_ calling recalc_chanctx_min_def
498 * due to maybe not returning from it, e.g in case new context was added
499 * first time with all parameters up to date.
501 ieee80211_chan_bw_change(local
, old_ctx
, true);
503 if (cfg80211_chandef_identical(&ctx
->conf
.def
, chandef
)) {
504 ieee80211_recalc_chanctx_min_def(local
, ctx
, rsvd_for
);
508 WARN_ON(!cfg80211_chandef_compatible(&ctx
->conf
.def
, chandef
));
510 ctx
->conf
.def
= *chandef
;
512 /* check if min chanctx also changed */
513 changed
= IEEE80211_CHANCTX_CHANGE_WIDTH
|
514 _ieee80211_recalc_chanctx_min_def(local
, ctx
, rsvd_for
);
515 drv_change_chanctx(local
, ctx
, changed
);
517 if (!local
->use_chanctx
) {
518 local
->_oper_chandef
= *chandef
;
519 ieee80211_hw_config(local
, 0);
522 /* check is BW wider */
523 ieee80211_chan_bw_change(local
, old_ctx
, false);
526 static void ieee80211_change_chanctx(struct ieee80211_local
*local
,
527 struct ieee80211_chanctx
*ctx
,
528 struct ieee80211_chanctx
*old_ctx
,
529 const struct cfg80211_chan_def
*chandef
)
531 _ieee80211_change_chanctx(local
, ctx
, old_ctx
, chandef
, NULL
);
534 static struct ieee80211_chanctx
*
535 ieee80211_find_chanctx(struct ieee80211_local
*local
,
536 const struct cfg80211_chan_def
*chandef
,
537 enum ieee80211_chanctx_mode mode
)
539 struct ieee80211_chanctx
*ctx
;
541 lockdep_assert_wiphy(local
->hw
.wiphy
);
543 if (mode
== IEEE80211_CHANCTX_EXCLUSIVE
)
546 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
547 const struct cfg80211_chan_def
*compat
;
549 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACE_NONE
)
552 if (ctx
->mode
== IEEE80211_CHANCTX_EXCLUSIVE
)
555 compat
= cfg80211_chandef_compatible(&ctx
->conf
.def
, chandef
);
559 compat
= ieee80211_chanctx_reserved_chandef(local
, ctx
,
564 ieee80211_change_chanctx(local
, ctx
, ctx
, compat
);
572 bool ieee80211_is_radar_required(struct ieee80211_local
*local
)
574 struct ieee80211_sub_if_data
*sdata
;
576 lockdep_assert_wiphy(local
->hw
.wiphy
);
579 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
580 unsigned int link_id
;
582 for (link_id
= 0; link_id
< ARRAY_SIZE(sdata
->link
); link_id
++) {
583 struct ieee80211_link_data
*link
;
585 link
= rcu_dereference(sdata
->link
[link_id
]);
587 if (link
&& link
->radar_required
) {
599 ieee80211_chanctx_radar_required(struct ieee80211_local
*local
,
600 struct ieee80211_chanctx
*ctx
)
602 struct ieee80211_chanctx_conf
*conf
= &ctx
->conf
;
603 struct ieee80211_sub_if_data
*sdata
;
604 bool required
= false;
606 lockdep_assert_wiphy(local
->hw
.wiphy
);
609 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
610 unsigned int link_id
;
612 if (!ieee80211_sdata_running(sdata
))
614 for (link_id
= 0; link_id
< ARRAY_SIZE(sdata
->link
); link_id
++) {
615 struct ieee80211_link_data
*link
;
617 link
= rcu_dereference(sdata
->link
[link_id
]);
621 if (rcu_access_pointer(link
->conf
->chanctx_conf
) != conf
)
623 if (!link
->radar_required
)
637 static struct ieee80211_chanctx
*
638 ieee80211_alloc_chanctx(struct ieee80211_local
*local
,
639 const struct cfg80211_chan_def
*chandef
,
640 enum ieee80211_chanctx_mode mode
)
642 struct ieee80211_chanctx
*ctx
;
644 lockdep_assert_wiphy(local
->hw
.wiphy
);
646 ctx
= kzalloc(sizeof(*ctx
) + local
->hw
.chanctx_data_size
, GFP_KERNEL
);
650 INIT_LIST_HEAD(&ctx
->assigned_links
);
651 INIT_LIST_HEAD(&ctx
->reserved_links
);
652 ctx
->conf
.def
= *chandef
;
653 ctx
->conf
.rx_chains_static
= 1;
654 ctx
->conf
.rx_chains_dynamic
= 1;
656 ctx
->conf
.radar_enabled
= false;
657 _ieee80211_recalc_chanctx_min_def(local
, ctx
, NULL
);
662 static int ieee80211_add_chanctx(struct ieee80211_local
*local
,
663 struct ieee80211_chanctx
*ctx
)
668 lockdep_assert_wiphy(local
->hw
.wiphy
);
670 if (!local
->use_chanctx
)
671 local
->hw
.conf
.radar_enabled
= ctx
->conf
.radar_enabled
;
673 /* turn idle off *before* setting channel -- some drivers need that */
674 changed
= ieee80211_idle_off(local
);
676 ieee80211_hw_config(local
, changed
);
678 if (!local
->use_chanctx
) {
679 local
->_oper_chandef
= ctx
->conf
.def
;
680 ieee80211_hw_config(local
, IEEE80211_CONF_CHANGE_CHANNEL
);
682 err
= drv_add_chanctx(local
, ctx
);
684 ieee80211_recalc_idle(local
);
692 static struct ieee80211_chanctx
*
693 ieee80211_new_chanctx(struct ieee80211_local
*local
,
694 const struct cfg80211_chan_def
*chandef
,
695 enum ieee80211_chanctx_mode mode
)
697 struct ieee80211_chanctx
*ctx
;
700 lockdep_assert_wiphy(local
->hw
.wiphy
);
702 ctx
= ieee80211_alloc_chanctx(local
, chandef
, mode
);
704 return ERR_PTR(-ENOMEM
);
706 err
= ieee80211_add_chanctx(local
, ctx
);
712 list_add_rcu(&ctx
->list
, &local
->chanctx_list
);
716 static void ieee80211_del_chanctx(struct ieee80211_local
*local
,
717 struct ieee80211_chanctx
*ctx
)
719 lockdep_assert_wiphy(local
->hw
.wiphy
);
721 if (!local
->use_chanctx
) {
722 struct cfg80211_chan_def
*chandef
= &local
->_oper_chandef
;
723 /* S1G doesn't have 20MHz, so get the correct width for the
726 if (chandef
->chan
->band
== NL80211_BAND_S1GHZ
)
728 ieee80211_s1g_channel_width(chandef
->chan
);
730 chandef
->width
= NL80211_CHAN_WIDTH_20_NOHT
;
731 chandef
->center_freq1
= chandef
->chan
->center_freq
;
732 chandef
->freq1_offset
= chandef
->chan
->freq_offset
;
733 chandef
->center_freq2
= 0;
735 /* NOTE: Disabling radar is only valid here for
736 * single channel context. To be sure, check it ...
738 WARN_ON(local
->hw
.conf
.radar_enabled
&&
739 !list_empty(&local
->chanctx_list
));
741 local
->hw
.conf
.radar_enabled
= false;
743 ieee80211_hw_config(local
, IEEE80211_CONF_CHANGE_CHANNEL
);
745 drv_remove_chanctx(local
, ctx
);
748 ieee80211_recalc_idle(local
);
751 static void ieee80211_free_chanctx(struct ieee80211_local
*local
,
752 struct ieee80211_chanctx
*ctx
)
754 lockdep_assert_wiphy(local
->hw
.wiphy
);
756 WARN_ON_ONCE(ieee80211_chanctx_refcount(local
, ctx
) != 0);
758 list_del_rcu(&ctx
->list
);
759 ieee80211_del_chanctx(local
, ctx
);
760 kfree_rcu(ctx
, rcu_head
);
763 void ieee80211_recalc_chanctx_chantype(struct ieee80211_local
*local
,
764 struct ieee80211_chanctx
*ctx
)
766 struct ieee80211_chanctx_conf
*conf
= &ctx
->conf
;
767 struct ieee80211_sub_if_data
*sdata
;
768 const struct cfg80211_chan_def
*compat
= NULL
;
769 struct sta_info
*sta
;
771 lockdep_assert_wiphy(local
->hw
.wiphy
);
774 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
777 if (!ieee80211_sdata_running(sdata
))
780 if (sdata
->vif
.type
== NL80211_IFTYPE_AP_VLAN
)
783 for (link_id
= 0; link_id
< ARRAY_SIZE(sdata
->link
); link_id
++) {
784 struct ieee80211_bss_conf
*link_conf
=
785 rcu_dereference(sdata
->vif
.link_conf
[link_id
]);
790 if (rcu_access_pointer(link_conf
->chanctx_conf
) != conf
)
794 compat
= &link_conf
->chandef
;
796 compat
= cfg80211_chandef_compatible(&link_conf
->chandef
,
798 if (WARN_ON_ONCE(!compat
))
803 if (WARN_ON_ONCE(!compat
)) {
808 /* TDLS peers can sometimes affect the chandef width */
809 list_for_each_entry_rcu(sta
, &local
->sta_list
, list
) {
810 if (!sta
->uploaded
||
811 !test_sta_flag(sta
, WLAN_STA_TDLS_WIDER_BW
) ||
812 !test_sta_flag(sta
, WLAN_STA_AUTHORIZED
) ||
813 !sta
->tdls_chandef
.chan
)
816 compat
= cfg80211_chandef_compatible(&sta
->tdls_chandef
,
818 if (WARN_ON_ONCE(!compat
))
826 ieee80211_change_chanctx(local
, ctx
, ctx
, compat
);
829 static void ieee80211_recalc_radar_chanctx(struct ieee80211_local
*local
,
830 struct ieee80211_chanctx
*chanctx
)
834 lockdep_assert_wiphy(local
->hw
.wiphy
);
836 radar_enabled
= ieee80211_chanctx_radar_required(local
, chanctx
);
838 if (radar_enabled
== chanctx
->conf
.radar_enabled
)
841 chanctx
->conf
.radar_enabled
= radar_enabled
;
843 if (!local
->use_chanctx
) {
844 local
->hw
.conf
.radar_enabled
= chanctx
->conf
.radar_enabled
;
845 ieee80211_hw_config(local
, IEEE80211_CONF_CHANGE_CHANNEL
);
848 drv_change_chanctx(local
, chanctx
, IEEE80211_CHANCTX_CHANGE_RADAR
);
851 static int ieee80211_assign_link_chanctx(struct ieee80211_link_data
*link
,
852 struct ieee80211_chanctx
*new_ctx
)
854 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
855 struct ieee80211_local
*local
= sdata
->local
;
856 struct ieee80211_chanctx_conf
*conf
;
857 struct ieee80211_chanctx
*curr_ctx
= NULL
;
860 if (WARN_ON(sdata
->vif
.type
== NL80211_IFTYPE_NAN
))
863 conf
= rcu_dereference_protected(link
->conf
->chanctx_conf
,
864 lockdep_is_held(&local
->hw
.wiphy
->mtx
));
867 curr_ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
869 drv_unassign_vif_chanctx(local
, sdata
, link
->conf
, curr_ctx
);
871 list_del(&link
->assigned_chanctx_list
);
875 /* recalc considering the link we'll use it for now */
876 ieee80211_recalc_chanctx_min_def(local
, new_ctx
, link
);
878 ret
= drv_assign_vif_chanctx(local
, sdata
, link
->conf
, new_ctx
);
882 conf
= &new_ctx
->conf
;
883 list_add(&link
->assigned_chanctx_list
,
884 &new_ctx
->assigned_links
);
888 rcu_assign_pointer(link
->conf
->chanctx_conf
, conf
);
890 sdata
->vif
.cfg
.idle
= !conf
;
892 if (curr_ctx
&& ieee80211_chanctx_num_assigned(local
, curr_ctx
) > 0) {
893 ieee80211_recalc_chanctx_chantype(local
, curr_ctx
);
894 ieee80211_recalc_smps_chanctx(local
, curr_ctx
);
895 ieee80211_recalc_radar_chanctx(local
, curr_ctx
);
896 ieee80211_recalc_chanctx_min_def(local
, curr_ctx
, NULL
);
899 if (new_ctx
&& ieee80211_chanctx_num_assigned(local
, new_ctx
) > 0) {
900 ieee80211_recalc_txpower(sdata
, false);
901 ieee80211_recalc_chanctx_min_def(local
, new_ctx
, NULL
);
904 if (sdata
->vif
.type
!= NL80211_IFTYPE_P2P_DEVICE
&&
905 sdata
->vif
.type
!= NL80211_IFTYPE_MONITOR
)
906 ieee80211_vif_cfg_change_notify(sdata
, BSS_CHANGED_IDLE
);
908 ieee80211_check_fast_xmit_iface(sdata
);
913 void ieee80211_recalc_smps_chanctx(struct ieee80211_local
*local
,
914 struct ieee80211_chanctx
*chanctx
)
916 struct ieee80211_sub_if_data
*sdata
;
917 u8 rx_chains_static
, rx_chains_dynamic
;
919 lockdep_assert_wiphy(local
->hw
.wiphy
);
921 rx_chains_static
= 1;
922 rx_chains_dynamic
= 1;
925 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
926 u8 needed_static
, needed_dynamic
;
927 unsigned int link_id
;
929 if (!ieee80211_sdata_running(sdata
))
932 switch (sdata
->vif
.type
) {
933 case NL80211_IFTYPE_STATION
:
934 if (!sdata
->u
.mgd
.associated
)
937 case NL80211_IFTYPE_AP
:
938 case NL80211_IFTYPE_ADHOC
:
939 case NL80211_IFTYPE_MESH_POINT
:
940 case NL80211_IFTYPE_OCB
:
946 for (link_id
= 0; link_id
< ARRAY_SIZE(sdata
->link
); link_id
++) {
947 struct ieee80211_link_data
*link
;
949 link
= rcu_dereference(sdata
->link
[link_id
]);
954 if (rcu_access_pointer(link
->conf
->chanctx_conf
) != &chanctx
->conf
)
957 switch (link
->smps_mode
) {
959 WARN_ONCE(1, "Invalid SMPS mode %d\n",
962 case IEEE80211_SMPS_OFF
:
963 needed_static
= link
->needed_rx_chains
;
964 needed_dynamic
= link
->needed_rx_chains
;
966 case IEEE80211_SMPS_DYNAMIC
:
968 needed_dynamic
= link
->needed_rx_chains
;
970 case IEEE80211_SMPS_STATIC
:
976 rx_chains_static
= max(rx_chains_static
, needed_static
);
977 rx_chains_dynamic
= max(rx_chains_dynamic
, needed_dynamic
);
981 /* Disable SMPS for the monitor interface */
982 sdata
= rcu_dereference(local
->monitor_sdata
);
984 rcu_access_pointer(sdata
->vif
.bss_conf
.chanctx_conf
) == &chanctx
->conf
)
985 rx_chains_dynamic
= rx_chains_static
= local
->rx_chains
;
989 if (!local
->use_chanctx
) {
990 if (rx_chains_static
> 1)
991 local
->smps_mode
= IEEE80211_SMPS_OFF
;
992 else if (rx_chains_dynamic
> 1)
993 local
->smps_mode
= IEEE80211_SMPS_DYNAMIC
;
995 local
->smps_mode
= IEEE80211_SMPS_STATIC
;
996 ieee80211_hw_config(local
, 0);
999 if (rx_chains_static
== chanctx
->conf
.rx_chains_static
&&
1000 rx_chains_dynamic
== chanctx
->conf
.rx_chains_dynamic
)
1003 chanctx
->conf
.rx_chains_static
= rx_chains_static
;
1004 chanctx
->conf
.rx_chains_dynamic
= rx_chains_dynamic
;
1005 drv_change_chanctx(local
, chanctx
, IEEE80211_CHANCTX_CHANGE_RX_CHAINS
);
1009 __ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data
*link
,
1012 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1013 unsigned int link_id
= link
->link_id
;
1014 struct ieee80211_bss_conf
*link_conf
= link
->conf
;
1015 struct ieee80211_local
*local __maybe_unused
= sdata
->local
;
1016 struct ieee80211_sub_if_data
*vlan
;
1017 struct ieee80211_chanctx_conf
*conf
;
1019 if (WARN_ON(sdata
->vif
.type
!= NL80211_IFTYPE_AP
))
1022 lockdep_assert_wiphy(local
->hw
.wiphy
);
1024 /* Check that conf exists, even when clearing this function
1025 * must be called with the AP's channel context still there
1026 * as it would otherwise cause VLANs to have an invalid
1027 * channel context pointer for a while, possibly pointing
1028 * to a channel context that has already been freed.
1030 conf
= rcu_dereference_protected(link_conf
->chanctx_conf
,
1031 lockdep_is_held(&local
->hw
.wiphy
->mtx
));
1038 list_for_each_entry(vlan
, &sdata
->u
.ap
.vlans
, u
.vlan
.list
) {
1039 struct ieee80211_bss_conf
*vlan_conf
;
1041 vlan_conf
= rcu_dereference(vlan
->vif
.link_conf
[link_id
]);
1042 if (WARN_ON(!vlan_conf
))
1045 rcu_assign_pointer(vlan_conf
->chanctx_conf
, conf
);
1050 void ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data
*link
,
1053 struct ieee80211_local
*local
= link
->sdata
->local
;
1055 lockdep_assert_wiphy(local
->hw
.wiphy
);
1057 __ieee80211_link_copy_chanctx_to_vlans(link
, clear
);
1060 int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data
*link
)
1062 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1063 struct ieee80211_chanctx
*ctx
= link
->reserved_chanctx
;
1065 lockdep_assert_wiphy(sdata
->local
->hw
.wiphy
);
1070 list_del(&link
->reserved_chanctx_list
);
1071 link
->reserved_chanctx
= NULL
;
1073 if (ieee80211_chanctx_refcount(sdata
->local
, ctx
) == 0) {
1074 if (ctx
->replace_state
== IEEE80211_CHANCTX_REPLACES_OTHER
) {
1075 if (WARN_ON(!ctx
->replace_ctx
))
1078 WARN_ON(ctx
->replace_ctx
->replace_state
!=
1079 IEEE80211_CHANCTX_WILL_BE_REPLACED
);
1080 WARN_ON(ctx
->replace_ctx
->replace_ctx
!= ctx
);
1082 ctx
->replace_ctx
->replace_ctx
= NULL
;
1083 ctx
->replace_ctx
->replace_state
=
1084 IEEE80211_CHANCTX_REPLACE_NONE
;
1086 list_del_rcu(&ctx
->list
);
1087 kfree_rcu(ctx
, rcu_head
);
1089 ieee80211_free_chanctx(sdata
->local
, ctx
);
1096 int ieee80211_link_reserve_chanctx(struct ieee80211_link_data
*link
,
1097 const struct cfg80211_chan_def
*chandef
,
1098 enum ieee80211_chanctx_mode mode
,
1099 bool radar_required
)
1101 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1102 struct ieee80211_local
*local
= sdata
->local
;
1103 struct ieee80211_chanctx
*new_ctx
, *curr_ctx
, *ctx
;
1105 lockdep_assert_wiphy(local
->hw
.wiphy
);
1107 curr_ctx
= ieee80211_link_get_chanctx(link
);
1108 if (curr_ctx
&& local
->use_chanctx
&& !local
->ops
->switch_vif_chanctx
)
1111 new_ctx
= ieee80211_find_reservation_chanctx(local
, chandef
, mode
);
1113 if (ieee80211_can_create_new_chanctx(local
)) {
1114 new_ctx
= ieee80211_new_chanctx(local
, chandef
, mode
);
1115 if (IS_ERR(new_ctx
))
1116 return PTR_ERR(new_ctx
);
1119 (curr_ctx
->replace_state
==
1120 IEEE80211_CHANCTX_WILL_BE_REPLACED
) ||
1121 !list_empty(&curr_ctx
->reserved_links
)) {
1123 * Another link already requested this context
1124 * for a reservation. Find another one hoping
1125 * all links assigned to it will also switch
1128 * TODO: This needs a little more work as some
1129 * cases (more than 2 chanctx capable devices)
1130 * may fail which could otherwise succeed
1131 * provided some channel context juggling was
1134 * Consider ctx1..3, link1..6, each ctx has 2
1135 * links. link1 and link2 from ctx1 request new
1136 * different chandefs starting 2 in-place
1137 * reserations with ctx4 and ctx5 replacing
1138 * ctx1 and ctx2 respectively. Next link5 and
1139 * link6 from ctx3 reserve ctx4. If link3 and
1140 * link4 remain on ctx2 as they are then this
1141 * fails unless `replace_ctx` from ctx5 is
1142 * replaced with ctx3.
1144 list_for_each_entry(ctx
, &local
->chanctx_list
,
1146 if (ctx
->replace_state
!=
1147 IEEE80211_CHANCTX_REPLACE_NONE
)
1150 if (!list_empty(&ctx
->reserved_links
))
1159 * If that's true then all available contexts already
1160 * have reservations and cannot be used.
1163 (curr_ctx
->replace_state
==
1164 IEEE80211_CHANCTX_WILL_BE_REPLACED
) ||
1165 !list_empty(&curr_ctx
->reserved_links
))
1168 new_ctx
= ieee80211_alloc_chanctx(local
, chandef
, mode
);
1172 new_ctx
->replace_ctx
= curr_ctx
;
1173 new_ctx
->replace_state
=
1174 IEEE80211_CHANCTX_REPLACES_OTHER
;
1176 curr_ctx
->replace_ctx
= new_ctx
;
1177 curr_ctx
->replace_state
=
1178 IEEE80211_CHANCTX_WILL_BE_REPLACED
;
1180 list_add_rcu(&new_ctx
->list
, &local
->chanctx_list
);
1184 list_add(&link
->reserved_chanctx_list
, &new_ctx
->reserved_links
);
1185 link
->reserved_chanctx
= new_ctx
;
1186 link
->reserved_chandef
= *chandef
;
1187 link
->reserved_radar_required
= radar_required
;
1188 link
->reserved_ready
= false;
1194 ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data
*link
)
1196 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1198 switch (sdata
->vif
.type
) {
1199 case NL80211_IFTYPE_ADHOC
:
1200 case NL80211_IFTYPE_AP
:
1201 case NL80211_IFTYPE_MESH_POINT
:
1202 case NL80211_IFTYPE_OCB
:
1203 wiphy_work_queue(sdata
->local
->hw
.wiphy
,
1204 &link
->csa_finalize_work
);
1206 case NL80211_IFTYPE_STATION
:
1207 wiphy_delayed_work_queue(sdata
->local
->hw
.wiphy
,
1208 &link
->u
.mgd
.chswitch_work
, 0);
1210 case NL80211_IFTYPE_UNSPECIFIED
:
1211 case NL80211_IFTYPE_AP_VLAN
:
1212 case NL80211_IFTYPE_WDS
:
1213 case NL80211_IFTYPE_MONITOR
:
1214 case NL80211_IFTYPE_P2P_CLIENT
:
1215 case NL80211_IFTYPE_P2P_GO
:
1216 case NL80211_IFTYPE_P2P_DEVICE
:
1217 case NL80211_IFTYPE_NAN
:
1218 case NUM_NL80211_IFTYPES
:
1225 ieee80211_link_update_chandef(struct ieee80211_link_data
*link
,
1226 const struct cfg80211_chan_def
*chandef
)
1228 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1229 unsigned int link_id
= link
->link_id
;
1230 struct ieee80211_sub_if_data
*vlan
;
1232 link
->conf
->chandef
= *chandef
;
1234 if (sdata
->vif
.type
!= NL80211_IFTYPE_AP
)
1238 list_for_each_entry(vlan
, &sdata
->u
.ap
.vlans
, u
.vlan
.list
) {
1239 struct ieee80211_bss_conf
*vlan_conf
;
1241 vlan_conf
= rcu_dereference(vlan
->vif
.link_conf
[link_id
]);
1242 if (WARN_ON(!vlan_conf
))
1245 vlan_conf
->chandef
= *chandef
;
1251 ieee80211_link_use_reserved_reassign(struct ieee80211_link_data
*link
)
1253 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1254 struct ieee80211_bss_conf
*link_conf
= link
->conf
;
1255 struct ieee80211_local
*local
= sdata
->local
;
1256 struct ieee80211_vif_chanctx_switch vif_chsw
[1] = {};
1257 struct ieee80211_chanctx
*old_ctx
, *new_ctx
;
1258 const struct cfg80211_chan_def
*chandef
;
1262 lockdep_assert_wiphy(local
->hw
.wiphy
);
1264 new_ctx
= link
->reserved_chanctx
;
1265 old_ctx
= ieee80211_link_get_chanctx(link
);
1267 if (WARN_ON(!link
->reserved_ready
))
1270 if (WARN_ON(!new_ctx
))
1273 if (WARN_ON(!old_ctx
))
1276 if (WARN_ON(new_ctx
->replace_state
==
1277 IEEE80211_CHANCTX_REPLACES_OTHER
))
1280 chandef
= ieee80211_chanctx_non_reserved_chandef(local
, new_ctx
,
1281 &link
->reserved_chandef
);
1282 if (WARN_ON(!chandef
))
1285 if (link_conf
->chandef
.width
!= link
->reserved_chandef
.width
)
1286 changed
= BSS_CHANGED_BANDWIDTH
;
1288 ieee80211_link_update_chandef(link
, &link
->reserved_chandef
);
1290 _ieee80211_change_chanctx(local
, new_ctx
, old_ctx
, chandef
, link
);
1292 vif_chsw
[0].vif
= &sdata
->vif
;
1293 vif_chsw
[0].old_ctx
= &old_ctx
->conf
;
1294 vif_chsw
[0].new_ctx
= &new_ctx
->conf
;
1295 vif_chsw
[0].link_conf
= link
->conf
;
1297 list_del(&link
->reserved_chanctx_list
);
1298 link
->reserved_chanctx
= NULL
;
1300 err
= drv_switch_vif_chanctx(local
, vif_chsw
, 1,
1301 CHANCTX_SWMODE_REASSIGN_VIF
);
1303 if (ieee80211_chanctx_refcount(local
, new_ctx
) == 0)
1304 ieee80211_free_chanctx(local
, new_ctx
);
1309 list_move(&link
->assigned_chanctx_list
, &new_ctx
->assigned_links
);
1310 rcu_assign_pointer(link_conf
->chanctx_conf
, &new_ctx
->conf
);
1312 if (sdata
->vif
.type
== NL80211_IFTYPE_AP
)
1313 __ieee80211_link_copy_chanctx_to_vlans(link
, false);
1315 ieee80211_check_fast_xmit_iface(sdata
);
1317 if (ieee80211_chanctx_refcount(local
, old_ctx
) == 0)
1318 ieee80211_free_chanctx(local
, old_ctx
);
1320 ieee80211_recalc_chanctx_min_def(local
, new_ctx
, NULL
);
1321 ieee80211_recalc_smps_chanctx(local
, new_ctx
);
1322 ieee80211_recalc_radar_chanctx(local
, new_ctx
);
1325 ieee80211_link_info_change_notify(sdata
, link
, changed
);
1328 ieee80211_link_chanctx_reservation_complete(link
);
1333 ieee80211_link_use_reserved_assign(struct ieee80211_link_data
*link
)
1335 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1336 struct ieee80211_local
*local
= sdata
->local
;
1337 struct ieee80211_chanctx
*old_ctx
, *new_ctx
;
1338 const struct cfg80211_chan_def
*chandef
;
1341 old_ctx
= ieee80211_link_get_chanctx(link
);
1342 new_ctx
= link
->reserved_chanctx
;
1344 if (WARN_ON(!link
->reserved_ready
))
1347 if (WARN_ON(old_ctx
))
1350 if (WARN_ON(!new_ctx
))
1353 if (WARN_ON(new_ctx
->replace_state
==
1354 IEEE80211_CHANCTX_REPLACES_OTHER
))
1357 chandef
= ieee80211_chanctx_non_reserved_chandef(local
, new_ctx
,
1358 &link
->reserved_chandef
);
1359 if (WARN_ON(!chandef
))
1362 ieee80211_change_chanctx(local
, new_ctx
, new_ctx
, chandef
);
1364 list_del(&link
->reserved_chanctx_list
);
1365 link
->reserved_chanctx
= NULL
;
1367 err
= ieee80211_assign_link_chanctx(link
, new_ctx
);
1369 if (ieee80211_chanctx_refcount(local
, new_ctx
) == 0)
1370 ieee80211_free_chanctx(local
, new_ctx
);
1376 ieee80211_link_chanctx_reservation_complete(link
);
1381 ieee80211_link_has_in_place_reservation(struct ieee80211_link_data
*link
)
1383 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1384 struct ieee80211_chanctx
*old_ctx
, *new_ctx
;
1386 lockdep_assert_wiphy(sdata
->local
->hw
.wiphy
);
1388 new_ctx
= link
->reserved_chanctx
;
1389 old_ctx
= ieee80211_link_get_chanctx(link
);
1394 if (WARN_ON(!new_ctx
))
1397 if (old_ctx
->replace_state
!= IEEE80211_CHANCTX_WILL_BE_REPLACED
)
1400 if (new_ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1406 static int ieee80211_chsw_switch_hwconf(struct ieee80211_local
*local
,
1407 struct ieee80211_chanctx
*new_ctx
)
1409 const struct cfg80211_chan_def
*chandef
;
1411 lockdep_assert_wiphy(local
->hw
.wiphy
);
1413 chandef
= ieee80211_chanctx_reserved_chandef(local
, new_ctx
, NULL
);
1414 if (WARN_ON(!chandef
))
1417 local
->hw
.conf
.radar_enabled
= new_ctx
->conf
.radar_enabled
;
1418 local
->_oper_chandef
= *chandef
;
1419 ieee80211_hw_config(local
, 0);
1424 static int ieee80211_chsw_switch_vifs(struct ieee80211_local
*local
,
1427 struct ieee80211_vif_chanctx_switch
*vif_chsw
;
1428 struct ieee80211_link_data
*link
;
1429 struct ieee80211_chanctx
*ctx
, *old_ctx
;
1432 lockdep_assert_wiphy(local
->hw
.wiphy
);
1434 vif_chsw
= kcalloc(n_vifs
, sizeof(vif_chsw
[0]), GFP_KERNEL
);
1439 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
1440 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1443 if (WARN_ON(!ctx
->replace_ctx
)) {
1448 list_for_each_entry(link
, &ctx
->reserved_links
,
1449 reserved_chanctx_list
) {
1450 if (!ieee80211_link_has_in_place_reservation(link
))
1453 old_ctx
= ieee80211_link_get_chanctx(link
);
1454 vif_chsw
[i
].vif
= &link
->sdata
->vif
;
1455 vif_chsw
[i
].old_ctx
= &old_ctx
->conf
;
1456 vif_chsw
[i
].new_ctx
= &ctx
->conf
;
1457 vif_chsw
[i
].link_conf
= link
->conf
;
1463 err
= drv_switch_vif_chanctx(local
, vif_chsw
, n_vifs
,
1464 CHANCTX_SWMODE_SWAP_CONTEXTS
);
1471 static int ieee80211_chsw_switch_ctxs(struct ieee80211_local
*local
)
1473 struct ieee80211_chanctx
*ctx
;
1476 lockdep_assert_wiphy(local
->hw
.wiphy
);
1478 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
1479 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1482 if (!list_empty(&ctx
->replace_ctx
->assigned_links
))
1485 ieee80211_del_chanctx(local
, ctx
->replace_ctx
);
1486 err
= ieee80211_add_chanctx(local
, ctx
);
1494 WARN_ON(ieee80211_add_chanctx(local
, ctx
));
1495 list_for_each_entry_continue_reverse(ctx
, &local
->chanctx_list
, list
) {
1496 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1499 if (!list_empty(&ctx
->replace_ctx
->assigned_links
))
1502 ieee80211_del_chanctx(local
, ctx
);
1503 WARN_ON(ieee80211_add_chanctx(local
, ctx
->replace_ctx
));
1509 static int ieee80211_vif_use_reserved_switch(struct ieee80211_local
*local
)
1511 struct ieee80211_chanctx
*ctx
, *ctx_tmp
, *old_ctx
;
1512 struct ieee80211_chanctx
*new_ctx
= NULL
;
1513 int err
, n_assigned
, n_reserved
, n_ready
;
1514 int n_ctx
= 0, n_vifs_switch
= 0, n_vifs_assign
= 0, n_vifs_ctxless
= 0;
1516 lockdep_assert_wiphy(local
->hw
.wiphy
);
1519 * If there are 2 independent pairs of channel contexts performing
1520 * cross-switch of their vifs this code will still wait until both are
1521 * ready even though it could be possible to switch one before the
1524 * For practical reasons and code simplicity just do a single huge
1529 * Verify if the reservation is still feasible.
1530 * - if it's not then disconnect
1531 * - if it is but not all vifs necessary are ready then defer
1534 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
1535 struct ieee80211_link_data
*link
;
1537 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1540 if (WARN_ON(!ctx
->replace_ctx
)) {
1545 if (!local
->use_chanctx
)
1554 list_for_each_entry(link
, &ctx
->replace_ctx
->assigned_links
,
1555 assigned_chanctx_list
) {
1557 if (link
->reserved_chanctx
) {
1559 if (link
->reserved_ready
)
1564 if (n_assigned
!= n_reserved
) {
1565 if (n_ready
== n_reserved
) {
1566 wiphy_info(local
->hw
.wiphy
,
1567 "channel context reservation cannot be finalized because some interfaces aren't switching\n");
1575 ctx
->conf
.radar_enabled
= false;
1576 list_for_each_entry(link
, &ctx
->reserved_links
,
1577 reserved_chanctx_list
) {
1578 if (ieee80211_link_has_in_place_reservation(link
) &&
1579 !link
->reserved_ready
)
1582 old_ctx
= ieee80211_link_get_chanctx(link
);
1584 if (old_ctx
->replace_state
==
1585 IEEE80211_CHANCTX_WILL_BE_REPLACED
)
1593 if (link
->reserved_radar_required
)
1594 ctx
->conf
.radar_enabled
= true;
1598 if (WARN_ON(n_ctx
== 0) ||
1599 WARN_ON(n_vifs_switch
== 0 &&
1600 n_vifs_assign
== 0 &&
1601 n_vifs_ctxless
== 0) ||
1602 WARN_ON(n_ctx
> 1 && !local
->use_chanctx
) ||
1603 WARN_ON(!new_ctx
&& !local
->use_chanctx
)) {
1609 * All necessary vifs are ready. Perform the switch now depending on
1610 * reservations and driver capabilities.
1613 if (local
->use_chanctx
) {
1614 if (n_vifs_switch
> 0) {
1615 err
= ieee80211_chsw_switch_vifs(local
, n_vifs_switch
);
1620 if (n_vifs_assign
> 0 || n_vifs_ctxless
> 0) {
1621 err
= ieee80211_chsw_switch_ctxs(local
);
1626 err
= ieee80211_chsw_switch_hwconf(local
, new_ctx
);
1632 * Update all structures, values and pointers to point to new channel
1635 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
1636 struct ieee80211_link_data
*link
, *link_tmp
;
1638 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1641 if (WARN_ON(!ctx
->replace_ctx
)) {
1646 list_for_each_entry(link
, &ctx
->reserved_links
,
1647 reserved_chanctx_list
) {
1648 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1649 struct ieee80211_bss_conf
*link_conf
= link
->conf
;
1652 if (!ieee80211_link_has_in_place_reservation(link
))
1655 rcu_assign_pointer(link_conf
->chanctx_conf
,
1658 if (sdata
->vif
.type
== NL80211_IFTYPE_AP
)
1659 __ieee80211_link_copy_chanctx_to_vlans(link
,
1662 ieee80211_check_fast_xmit_iface(sdata
);
1664 link
->radar_required
= link
->reserved_radar_required
;
1666 if (link_conf
->chandef
.width
!= link
->reserved_chandef
.width
)
1667 changed
= BSS_CHANGED_BANDWIDTH
;
1669 ieee80211_link_update_chandef(link
, &link
->reserved_chandef
);
1671 ieee80211_link_info_change_notify(sdata
,
1675 ieee80211_recalc_txpower(sdata
, false);
1678 ieee80211_recalc_chanctx_chantype(local
, ctx
);
1679 ieee80211_recalc_smps_chanctx(local
, ctx
);
1680 ieee80211_recalc_radar_chanctx(local
, ctx
);
1681 ieee80211_recalc_chanctx_min_def(local
, ctx
, NULL
);
1683 list_for_each_entry_safe(link
, link_tmp
, &ctx
->reserved_links
,
1684 reserved_chanctx_list
) {
1685 if (ieee80211_link_get_chanctx(link
) != ctx
)
1688 list_del(&link
->reserved_chanctx_list
);
1689 list_move(&link
->assigned_chanctx_list
,
1690 &ctx
->assigned_links
);
1691 link
->reserved_chanctx
= NULL
;
1693 ieee80211_link_chanctx_reservation_complete(link
);
1697 * This context might have been a dependency for an already
1698 * ready re-assign reservation interface that was deferred. Do
1699 * not propagate error to the caller though. The in-place
1700 * reservation for originally requested interface has already
1701 * succeeded at this point.
1703 list_for_each_entry_safe(link
, link_tmp
, &ctx
->reserved_links
,
1704 reserved_chanctx_list
) {
1705 if (WARN_ON(ieee80211_link_has_in_place_reservation(link
)))
1708 if (WARN_ON(link
->reserved_chanctx
!= ctx
))
1711 if (!link
->reserved_ready
)
1714 if (ieee80211_link_get_chanctx(link
))
1715 err
= ieee80211_link_use_reserved_reassign(link
);
1717 err
= ieee80211_link_use_reserved_assign(link
);
1721 "failed to finalize (re-)assign reservation (err=%d)\n",
1723 ieee80211_link_unreserve_chanctx(link
);
1724 cfg80211_stop_iface(local
->hw
.wiphy
,
1732 * Finally free old contexts
1735 list_for_each_entry_safe(ctx
, ctx_tmp
, &local
->chanctx_list
, list
) {
1736 if (ctx
->replace_state
!= IEEE80211_CHANCTX_WILL_BE_REPLACED
)
1739 ctx
->replace_ctx
->replace_ctx
= NULL
;
1740 ctx
->replace_ctx
->replace_state
=
1741 IEEE80211_CHANCTX_REPLACE_NONE
;
1743 list_del_rcu(&ctx
->list
);
1744 kfree_rcu(ctx
, rcu_head
);
1750 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
1751 struct ieee80211_link_data
*link
, *link_tmp
;
1753 if (ctx
->replace_state
!= IEEE80211_CHANCTX_REPLACES_OTHER
)
1756 list_for_each_entry_safe(link
, link_tmp
, &ctx
->reserved_links
,
1757 reserved_chanctx_list
) {
1758 ieee80211_link_unreserve_chanctx(link
);
1759 ieee80211_link_chanctx_reservation_complete(link
);
1766 static void __ieee80211_link_release_channel(struct ieee80211_link_data
*link
)
1768 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1769 struct ieee80211_bss_conf
*link_conf
= link
->conf
;
1770 struct ieee80211_local
*local
= sdata
->local
;
1771 struct ieee80211_chanctx_conf
*conf
;
1772 struct ieee80211_chanctx
*ctx
;
1773 bool use_reserved_switch
= false;
1775 lockdep_assert_wiphy(local
->hw
.wiphy
);
1777 conf
= rcu_dereference_protected(link_conf
->chanctx_conf
,
1778 lockdep_is_held(&local
->hw
.wiphy
->mtx
));
1782 ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
1784 if (link
->reserved_chanctx
) {
1785 if (link
->reserved_chanctx
->replace_state
== IEEE80211_CHANCTX_REPLACES_OTHER
&&
1786 ieee80211_chanctx_num_reserved(local
, link
->reserved_chanctx
) > 1)
1787 use_reserved_switch
= true;
1789 ieee80211_link_unreserve_chanctx(link
);
1792 ieee80211_assign_link_chanctx(link
, NULL
);
1793 if (ieee80211_chanctx_refcount(local
, ctx
) == 0)
1794 ieee80211_free_chanctx(local
, ctx
);
1796 link
->radar_required
= false;
1798 /* Unreserving may ready an in-place reservation. */
1799 if (use_reserved_switch
)
1800 ieee80211_vif_use_reserved_switch(local
);
1803 int ieee80211_link_use_channel(struct ieee80211_link_data
*link
,
1804 const struct cfg80211_chan_def
*chandef
,
1805 enum ieee80211_chanctx_mode mode
)
1807 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1808 struct ieee80211_local
*local
= sdata
->local
;
1809 struct ieee80211_chanctx
*ctx
;
1810 u8 radar_detect_width
= 0;
1813 lockdep_assert_wiphy(local
->hw
.wiphy
);
1815 if (sdata
->vif
.active_links
&&
1816 !(sdata
->vif
.active_links
& BIT(link
->link_id
))) {
1817 ieee80211_link_update_chandef(link
, chandef
);
1821 ret
= cfg80211_chandef_dfs_required(local
->hw
.wiphy
,
1823 sdata
->wdev
.iftype
);
1827 radar_detect_width
= BIT(chandef
->width
);
1829 link
->radar_required
= ret
;
1831 ret
= ieee80211_check_combinations(sdata
, chandef
, mode
,
1832 radar_detect_width
);
1836 __ieee80211_link_release_channel(link
);
1838 ctx
= ieee80211_find_chanctx(local
, chandef
, mode
);
1840 ctx
= ieee80211_new_chanctx(local
, chandef
, mode
);
1846 ieee80211_link_update_chandef(link
, chandef
);
1848 ret
= ieee80211_assign_link_chanctx(link
, ctx
);
1850 /* if assign fails refcount stays the same */
1851 if (ieee80211_chanctx_refcount(local
, ctx
) == 0)
1852 ieee80211_free_chanctx(local
, ctx
);
1856 ieee80211_recalc_smps_chanctx(local
, ctx
);
1857 ieee80211_recalc_radar_chanctx(local
, ctx
);
1860 link
->radar_required
= false;
1865 int ieee80211_link_use_reserved_context(struct ieee80211_link_data
*link
)
1867 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1868 struct ieee80211_local
*local
= sdata
->local
;
1869 struct ieee80211_chanctx
*new_ctx
;
1870 struct ieee80211_chanctx
*old_ctx
;
1873 lockdep_assert_wiphy(local
->hw
.wiphy
);
1875 new_ctx
= link
->reserved_chanctx
;
1876 old_ctx
= ieee80211_link_get_chanctx(link
);
1878 if (WARN_ON(!new_ctx
))
1881 if (WARN_ON(new_ctx
->replace_state
==
1882 IEEE80211_CHANCTX_WILL_BE_REPLACED
))
1885 if (WARN_ON(link
->reserved_ready
))
1888 link
->reserved_ready
= true;
1890 if (new_ctx
->replace_state
== IEEE80211_CHANCTX_REPLACE_NONE
) {
1892 return ieee80211_link_use_reserved_reassign(link
);
1894 return ieee80211_link_use_reserved_assign(link
);
1898 * In-place reservation may need to be finalized now either if:
1899 * a) sdata is taking part in the swapping itself and is the last one
1900 * b) sdata has switched with a re-assign reservation to an existing
1901 * context readying in-place switching of old_ctx
1903 * In case of (b) do not propagate the error up because the requested
1904 * sdata already switched successfully. Just spill an extra warning.
1905 * The ieee80211_vif_use_reserved_switch() already stops all necessary
1906 * interfaces upon failure.
1909 old_ctx
->replace_state
== IEEE80211_CHANCTX_WILL_BE_REPLACED
) ||
1910 new_ctx
->replace_state
== IEEE80211_CHANCTX_REPLACES_OTHER
) {
1911 err
= ieee80211_vif_use_reserved_switch(local
);
1912 if (err
&& err
!= -EAGAIN
) {
1913 if (new_ctx
->replace_state
==
1914 IEEE80211_CHANCTX_REPLACES_OTHER
)
1917 wiphy_info(local
->hw
.wiphy
,
1918 "depending in-place reservation failed (err=%d)\n",
1926 int ieee80211_link_change_bandwidth(struct ieee80211_link_data
*link
,
1927 const struct cfg80211_chan_def
*chandef
,
1930 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1931 struct ieee80211_bss_conf
*link_conf
= link
->conf
;
1932 struct ieee80211_local
*local
= sdata
->local
;
1933 struct ieee80211_chanctx_conf
*conf
;
1934 struct ieee80211_chanctx
*ctx
;
1935 const struct cfg80211_chan_def
*compat
;
1937 lockdep_assert_wiphy(local
->hw
.wiphy
);
1939 if (!cfg80211_chandef_usable(sdata
->local
->hw
.wiphy
, chandef
,
1940 IEEE80211_CHAN_DISABLED
))
1943 if (cfg80211_chandef_identical(chandef
, &link_conf
->chandef
))
1946 if (chandef
->width
== NL80211_CHAN_WIDTH_20_NOHT
||
1947 link_conf
->chandef
.width
== NL80211_CHAN_WIDTH_20_NOHT
)
1950 conf
= rcu_dereference_protected(link_conf
->chanctx_conf
,
1951 lockdep_is_held(&local
->hw
.wiphy
->mtx
));
1955 ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
1957 compat
= cfg80211_chandef_compatible(&conf
->def
, chandef
);
1961 switch (ctx
->replace_state
) {
1962 case IEEE80211_CHANCTX_REPLACE_NONE
:
1963 if (!ieee80211_chanctx_reserved_chandef(local
, ctx
, compat
))
1966 case IEEE80211_CHANCTX_WILL_BE_REPLACED
:
1967 /* TODO: Perhaps the bandwidth change could be treated as a
1968 * reservation itself? */
1970 case IEEE80211_CHANCTX_REPLACES_OTHER
:
1971 /* channel context that is going to replace another channel
1972 * context doesn't really exist and shouldn't be assigned
1978 ieee80211_link_update_chandef(link
, chandef
);
1980 ieee80211_recalc_chanctx_chantype(local
, ctx
);
1982 *changed
|= BSS_CHANGED_BANDWIDTH
;
1986 void ieee80211_link_release_channel(struct ieee80211_link_data
*link
)
1988 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1990 lockdep_assert_wiphy(sdata
->local
->hw
.wiphy
);
1992 if (rcu_access_pointer(link
->conf
->chanctx_conf
))
1993 __ieee80211_link_release_channel(link
);
1996 void ieee80211_link_vlan_copy_chanctx(struct ieee80211_link_data
*link
)
1998 struct ieee80211_sub_if_data
*sdata
= link
->sdata
;
1999 unsigned int link_id
= link
->link_id
;
2000 struct ieee80211_bss_conf
*link_conf
= link
->conf
;
2001 struct ieee80211_bss_conf
*ap_conf
;
2002 struct ieee80211_local
*local
= sdata
->local
;
2003 struct ieee80211_sub_if_data
*ap
;
2004 struct ieee80211_chanctx_conf
*conf
;
2006 lockdep_assert_wiphy(local
->hw
.wiphy
);
2008 if (WARN_ON(sdata
->vif
.type
!= NL80211_IFTYPE_AP_VLAN
|| !sdata
->bss
))
2011 ap
= container_of(sdata
->bss
, struct ieee80211_sub_if_data
, u
.ap
);
2014 ap_conf
= rcu_dereference(ap
->vif
.link_conf
[link_id
]);
2015 conf
= rcu_dereference_protected(ap_conf
->chanctx_conf
,
2016 lockdep_is_held(&local
->hw
.wiphy
->mtx
));
2017 rcu_assign_pointer(link_conf
->chanctx_conf
, conf
);
2021 void ieee80211_iter_chan_contexts_atomic(
2022 struct ieee80211_hw
*hw
,
2023 void (*iter
)(struct ieee80211_hw
*hw
,
2024 struct ieee80211_chanctx_conf
*chanctx_conf
,
2028 struct ieee80211_local
*local
= hw_to_local(hw
);
2029 struct ieee80211_chanctx
*ctx
;
2032 list_for_each_entry_rcu(ctx
, &local
->chanctx_list
, list
)
2033 if (ctx
->driver_present
)
2034 iter(hw
, &ctx
->conf
, iter_data
);
2037 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic
);