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_held(&local->chanctx_mtx);
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_held(&local->chanctx_mtx);
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_held(&local->chanctx_mtx);
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_held(&local->chanctx_mtx);
66 return ieee80211_num_chanctx(local) < ieee80211_max_num_channels(local);
69 static struct ieee80211_chanctx *
70 ieee80211_link_get_chanctx(struct ieee80211_link_data *link)
72 struct ieee80211_local *local __maybe_unused = link->sdata->local;
73 struct ieee80211_chanctx_conf *conf;
75 conf = rcu_dereference_protected(link->conf->chanctx_conf,
76 lockdep_is_held(&local->chanctx_mtx));
80 return container_of(conf, struct ieee80211_chanctx, conf);
83 static const struct cfg80211_chan_def *
84 ieee80211_chanctx_reserved_chandef(struct ieee80211_local *local,
85 struct ieee80211_chanctx *ctx,
86 const struct cfg80211_chan_def *compat)
88 struct ieee80211_link_data *link;
90 lockdep_assert_held(&local->chanctx_mtx);
92 list_for_each_entry(link, &ctx->reserved_links,
93 reserved_chanctx_list) {
95 compat = &link->reserved_chandef;
97 compat = cfg80211_chandef_compatible(&link->reserved_chandef,
106 static const struct cfg80211_chan_def *
107 ieee80211_chanctx_non_reserved_chandef(struct ieee80211_local *local,
108 struct ieee80211_chanctx *ctx,
109 const struct cfg80211_chan_def *compat)
111 struct ieee80211_link_data *link;
113 lockdep_assert_held(&local->chanctx_mtx);
115 list_for_each_entry(link, &ctx->assigned_links,
116 assigned_chanctx_list) {
117 struct ieee80211_bss_conf *link_conf = link->conf;
119 if (link->reserved_chanctx)
123 compat = &link_conf->chandef;
125 compat = cfg80211_chandef_compatible(
126 &link_conf->chandef, compat);
134 static const struct cfg80211_chan_def *
135 ieee80211_chanctx_combined_chandef(struct ieee80211_local *local,
136 struct ieee80211_chanctx *ctx,
137 const struct cfg80211_chan_def *compat)
139 lockdep_assert_held(&local->chanctx_mtx);
141 compat = ieee80211_chanctx_reserved_chandef(local, ctx, compat);
145 compat = ieee80211_chanctx_non_reserved_chandef(local, ctx, compat);
153 ieee80211_chanctx_can_reserve_chandef(struct ieee80211_local *local,
154 struct ieee80211_chanctx *ctx,
155 const struct cfg80211_chan_def *def)
157 lockdep_assert_held(&local->chanctx_mtx);
159 if (ieee80211_chanctx_combined_chandef(local, ctx, def))
162 if (!list_empty(&ctx->reserved_links) &&
163 ieee80211_chanctx_reserved_chandef(local, ctx, def))
169 static struct ieee80211_chanctx *
170 ieee80211_find_reservation_chanctx(struct ieee80211_local *local,
171 const struct cfg80211_chan_def *chandef,
172 enum ieee80211_chanctx_mode mode)
174 struct ieee80211_chanctx *ctx;
176 lockdep_assert_held(&local->chanctx_mtx);
178 if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
181 list_for_each_entry(ctx, &local->chanctx_list, list) {
182 if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
185 if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
188 if (!ieee80211_chanctx_can_reserve_chandef(local, ctx,
198 static enum nl80211_chan_width ieee80211_get_sta_bw(struct sta_info *sta,
199 unsigned int link_id)
201 enum ieee80211_sta_rx_bandwidth width;
202 struct link_sta_info *link_sta;
204 link_sta = rcu_dereference(sta->link[link_id]);
206 /* no effect if this STA has no presence on this link */
208 return NL80211_CHAN_WIDTH_20_NOHT;
210 width = ieee80211_sta_cap_rx_bw(link_sta);
213 case IEEE80211_STA_RX_BW_20:
214 if (link_sta->pub->ht_cap.ht_supported)
215 return NL80211_CHAN_WIDTH_20;
217 return NL80211_CHAN_WIDTH_20_NOHT;
218 case IEEE80211_STA_RX_BW_40:
219 return NL80211_CHAN_WIDTH_40;
220 case IEEE80211_STA_RX_BW_80:
221 return NL80211_CHAN_WIDTH_80;
222 case IEEE80211_STA_RX_BW_160:
224 * This applied for both 160 and 80+80. since we use
225 * the returned value to consider degradation of
226 * ctx->conf.min_def, we have to make sure to take
227 * the bigger one (NL80211_CHAN_WIDTH_160).
228 * Otherwise we might try degrading even when not
229 * needed, as the max required sta_bw returned (80+80)
230 * might be smaller than the configured bw (160).
232 return NL80211_CHAN_WIDTH_160;
233 case IEEE80211_STA_RX_BW_320:
234 return NL80211_CHAN_WIDTH_320;
237 return NL80211_CHAN_WIDTH_20;
241 static enum nl80211_chan_width
242 ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata,
243 unsigned int link_id)
245 enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
246 struct sta_info *sta;
248 list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
249 if (sdata != sta->sdata &&
250 !(sta->sdata->bss && sta->sdata->bss == sdata->bss))
253 max_bw = max(max_bw, ieee80211_get_sta_bw(sta, link_id));
259 static enum nl80211_chan_width
260 ieee80211_get_chanctx_vif_max_required_bw(struct ieee80211_sub_if_data *sdata,
261 struct ieee80211_chanctx_conf *conf)
263 enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
264 struct ieee80211_vif *vif = &sdata->vif;
268 for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
269 enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT;
270 struct ieee80211_bss_conf *link_conf =
271 rcu_dereference(sdata->vif.link_conf[link_id]);
276 if (rcu_access_pointer(link_conf->chanctx_conf) != conf)
280 case NL80211_IFTYPE_AP:
281 case NL80211_IFTYPE_AP_VLAN:
282 width = ieee80211_get_max_required_bw(sdata, link_id);
284 case NL80211_IFTYPE_STATION:
286 * The ap's sta->bandwidth is not set yet at this
287 * point, so take the width from the chandef, but
288 * account also for TDLS peers
290 width = max(link_conf->chandef.width,
291 ieee80211_get_max_required_bw(sdata, link_id));
293 case NL80211_IFTYPE_P2P_DEVICE:
294 case NL80211_IFTYPE_NAN:
296 case NL80211_IFTYPE_ADHOC:
297 case NL80211_IFTYPE_MESH_POINT:
298 case NL80211_IFTYPE_OCB:
299 width = link_conf->chandef.width;
301 case NL80211_IFTYPE_WDS:
302 case NL80211_IFTYPE_UNSPECIFIED:
303 case NUM_NL80211_IFTYPES:
304 case NL80211_IFTYPE_MONITOR:
305 case NL80211_IFTYPE_P2P_CLIENT:
306 case NL80211_IFTYPE_P2P_GO:
310 max_bw = max(max_bw, width);
317 static enum nl80211_chan_width
318 ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
319 struct ieee80211_chanctx_conf *conf)
321 struct ieee80211_sub_if_data *sdata;
322 enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
325 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
326 enum nl80211_chan_width width;
328 if (!ieee80211_sdata_running(sdata))
331 width = ieee80211_get_chanctx_vif_max_required_bw(sdata, conf);
333 max_bw = max(max_bw, width);
336 /* use the configured bandwidth in case of monitor interface */
337 sdata = rcu_dereference(local->monitor_sdata);
339 rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == conf)
340 max_bw = max(max_bw, conf->def.width);
348 * recalc the min required chan width of the channel context, which is
349 * the max of min required widths of all the interfaces bound to this
352 static u32 _ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
353 struct ieee80211_chanctx *ctx)
355 enum nl80211_chan_width max_bw;
356 struct cfg80211_chan_def min_def;
358 lockdep_assert_held(&local->chanctx_mtx);
360 /* don't optimize non-20MHz based and radar_enabled confs */
361 if (ctx->conf.def.width == NL80211_CHAN_WIDTH_5 ||
362 ctx->conf.def.width == NL80211_CHAN_WIDTH_10 ||
363 ctx->conf.def.width == NL80211_CHAN_WIDTH_1 ||
364 ctx->conf.def.width == NL80211_CHAN_WIDTH_2 ||
365 ctx->conf.def.width == NL80211_CHAN_WIDTH_4 ||
366 ctx->conf.def.width == NL80211_CHAN_WIDTH_8 ||
367 ctx->conf.def.width == NL80211_CHAN_WIDTH_16 ||
368 ctx->conf.radar_enabled) {
369 ctx->conf.min_def = ctx->conf.def;
373 max_bw = ieee80211_get_chanctx_max_required_bw(local, &ctx->conf);
375 /* downgrade chandef up to max_bw */
376 min_def = ctx->conf.def;
377 while (min_def.width > max_bw)
378 ieee80211_chandef_downgrade(&min_def);
380 if (cfg80211_chandef_identical(&ctx->conf.min_def, &min_def))
383 ctx->conf.min_def = min_def;
384 if (!ctx->driver_present)
387 return IEEE80211_CHANCTX_CHANGE_MIN_WIDTH;
390 /* calling this function is assuming that station vif is updated to
391 * lates changes by calling ieee80211_link_update_chandef
393 static void ieee80211_chan_bw_change(struct ieee80211_local *local,
394 struct ieee80211_chanctx *ctx,
397 struct sta_info *sta;
398 struct ieee80211_supported_band *sband =
399 local->hw.wiphy->bands[ctx->conf.def.chan->band];
402 list_for_each_entry_rcu(sta, &local->sta_list,
404 struct ieee80211_sub_if_data *sdata = sta->sdata;
405 enum ieee80211_sta_rx_bandwidth new_sta_bw;
406 unsigned int link_id;
408 if (!ieee80211_sdata_running(sta->sdata))
411 for (link_id = 0; link_id < ARRAY_SIZE(sta->sdata->link); link_id++) {
412 struct ieee80211_bss_conf *link_conf =
413 rcu_dereference(sdata->vif.link_conf[link_id]);
414 struct link_sta_info *link_sta;
419 if (rcu_access_pointer(link_conf->chanctx_conf) != &ctx->conf)
422 link_sta = rcu_dereference(sta->link[link_id]);
426 new_sta_bw = ieee80211_sta_cur_vht_bw(link_sta);
429 if (new_sta_bw == link_sta->pub->bandwidth)
432 /* vif changed to narrow BW and narrow BW for station wasn't
433 * requested or vise versa */
434 if ((new_sta_bw < link_sta->pub->bandwidth) == !narrowed)
437 link_sta->pub->bandwidth = new_sta_bw;
438 rate_control_rate_update(local, sband, sta, link_id,
439 IEEE80211_RC_BW_CHANGED);
446 * recalc the min required chan width of the channel context, which is
447 * the max of min required widths of all the interfaces bound to this
450 void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
451 struct ieee80211_chanctx *ctx)
453 u32 changed = _ieee80211_recalc_chanctx_min_def(local, ctx);
458 /* check is BW narrowed */
459 ieee80211_chan_bw_change(local, ctx, true);
461 drv_change_chanctx(local, ctx, changed);
463 /* check is BW wider */
464 ieee80211_chan_bw_change(local, ctx, false);
467 static void ieee80211_change_chanctx(struct ieee80211_local *local,
468 struct ieee80211_chanctx *ctx,
469 struct ieee80211_chanctx *old_ctx,
470 const struct cfg80211_chan_def *chandef)
474 /* expected to handle only 20/40/80/160/320 channel widths */
475 switch (chandef->width) {
476 case NL80211_CHAN_WIDTH_20_NOHT:
477 case NL80211_CHAN_WIDTH_20:
478 case NL80211_CHAN_WIDTH_40:
479 case NL80211_CHAN_WIDTH_80:
480 case NL80211_CHAN_WIDTH_80P80:
481 case NL80211_CHAN_WIDTH_160:
482 case NL80211_CHAN_WIDTH_320:
488 /* Check maybe BW narrowed - we do this _before_ calling recalc_chanctx_min_def
489 * due to maybe not returning from it, e.g in case new context was added
490 * first time with all parameters up to date.
492 ieee80211_chan_bw_change(local, old_ctx, true);
494 if (cfg80211_chandef_identical(&ctx->conf.def, chandef)) {
495 ieee80211_recalc_chanctx_min_def(local, ctx);
499 WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
501 ctx->conf.def = *chandef;
503 /* check if min chanctx also changed */
504 changed = IEEE80211_CHANCTX_CHANGE_WIDTH |
505 _ieee80211_recalc_chanctx_min_def(local, ctx);
506 drv_change_chanctx(local, ctx, changed);
508 if (!local->use_chanctx) {
509 local->_oper_chandef = *chandef;
510 ieee80211_hw_config(local, 0);
513 /* check is BW wider */
514 ieee80211_chan_bw_change(local, old_ctx, false);
517 static struct ieee80211_chanctx *
518 ieee80211_find_chanctx(struct ieee80211_local *local,
519 const struct cfg80211_chan_def *chandef,
520 enum ieee80211_chanctx_mode mode)
522 struct ieee80211_chanctx *ctx;
524 lockdep_assert_held(&local->chanctx_mtx);
526 if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
529 list_for_each_entry(ctx, &local->chanctx_list, list) {
530 const struct cfg80211_chan_def *compat;
532 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACE_NONE)
535 if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
538 compat = cfg80211_chandef_compatible(&ctx->conf.def, chandef);
542 compat = ieee80211_chanctx_reserved_chandef(local, ctx,
547 ieee80211_change_chanctx(local, ctx, ctx, compat);
555 bool ieee80211_is_radar_required(struct ieee80211_local *local)
557 struct ieee80211_sub_if_data *sdata;
559 lockdep_assert_held(&local->mtx);
562 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
563 unsigned int link_id;
565 for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
566 struct ieee80211_link_data *link;
568 link = rcu_dereference(sdata->link[link_id]);
570 if (link && link->radar_required) {
582 ieee80211_chanctx_radar_required(struct ieee80211_local *local,
583 struct ieee80211_chanctx *ctx)
585 struct ieee80211_chanctx_conf *conf = &ctx->conf;
586 struct ieee80211_sub_if_data *sdata;
587 bool required = false;
589 lockdep_assert_held(&local->chanctx_mtx);
590 lockdep_assert_held(&local->mtx);
593 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
594 unsigned int link_id;
596 if (!ieee80211_sdata_running(sdata))
598 for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
599 struct ieee80211_link_data *link;
601 link = rcu_dereference(sdata->link[link_id]);
605 if (rcu_access_pointer(link->conf->chanctx_conf) != conf)
607 if (!link->radar_required)
621 static struct ieee80211_chanctx *
622 ieee80211_alloc_chanctx(struct ieee80211_local *local,
623 const struct cfg80211_chan_def *chandef,
624 enum ieee80211_chanctx_mode mode)
626 struct ieee80211_chanctx *ctx;
628 lockdep_assert_held(&local->chanctx_mtx);
630 ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL);
634 INIT_LIST_HEAD(&ctx->assigned_links);
635 INIT_LIST_HEAD(&ctx->reserved_links);
636 ctx->conf.def = *chandef;
637 ctx->conf.rx_chains_static = 1;
638 ctx->conf.rx_chains_dynamic = 1;
640 ctx->conf.radar_enabled = false;
641 ieee80211_recalc_chanctx_min_def(local, ctx);
646 static int ieee80211_add_chanctx(struct ieee80211_local *local,
647 struct ieee80211_chanctx *ctx)
652 lockdep_assert_held(&local->mtx);
653 lockdep_assert_held(&local->chanctx_mtx);
655 if (!local->use_chanctx)
656 local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
658 /* turn idle off *before* setting channel -- some drivers need that */
659 changed = ieee80211_idle_off(local);
661 ieee80211_hw_config(local, changed);
663 if (!local->use_chanctx) {
664 local->_oper_chandef = ctx->conf.def;
665 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
667 err = drv_add_chanctx(local, ctx);
669 ieee80211_recalc_idle(local);
677 static struct ieee80211_chanctx *
678 ieee80211_new_chanctx(struct ieee80211_local *local,
679 const struct cfg80211_chan_def *chandef,
680 enum ieee80211_chanctx_mode mode)
682 struct ieee80211_chanctx *ctx;
685 lockdep_assert_held(&local->mtx);
686 lockdep_assert_held(&local->chanctx_mtx);
688 ctx = ieee80211_alloc_chanctx(local, chandef, mode);
690 return ERR_PTR(-ENOMEM);
692 err = ieee80211_add_chanctx(local, ctx);
698 list_add_rcu(&ctx->list, &local->chanctx_list);
702 static void ieee80211_del_chanctx(struct ieee80211_local *local,
703 struct ieee80211_chanctx *ctx)
705 lockdep_assert_held(&local->chanctx_mtx);
707 if (!local->use_chanctx) {
708 struct cfg80211_chan_def *chandef = &local->_oper_chandef;
709 /* S1G doesn't have 20MHz, so get the correct width for the
712 if (chandef->chan->band == NL80211_BAND_S1GHZ)
714 ieee80211_s1g_channel_width(chandef->chan);
716 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
717 chandef->center_freq1 = chandef->chan->center_freq;
718 chandef->freq1_offset = chandef->chan->freq_offset;
719 chandef->center_freq2 = 0;
721 /* NOTE: Disabling radar is only valid here for
722 * single channel context. To be sure, check it ...
724 WARN_ON(local->hw.conf.radar_enabled &&
725 !list_empty(&local->chanctx_list));
727 local->hw.conf.radar_enabled = false;
729 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
731 drv_remove_chanctx(local, ctx);
734 ieee80211_recalc_idle(local);
737 static void ieee80211_free_chanctx(struct ieee80211_local *local,
738 struct ieee80211_chanctx *ctx)
740 lockdep_assert_held(&local->chanctx_mtx);
742 WARN_ON_ONCE(ieee80211_chanctx_refcount(local, ctx) != 0);
744 list_del_rcu(&ctx->list);
745 ieee80211_del_chanctx(local, ctx);
746 kfree_rcu(ctx, rcu_head);
749 void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
750 struct ieee80211_chanctx *ctx)
752 struct ieee80211_chanctx_conf *conf = &ctx->conf;
753 struct ieee80211_sub_if_data *sdata;
754 const struct cfg80211_chan_def *compat = NULL;
755 struct sta_info *sta;
757 lockdep_assert_held(&local->chanctx_mtx);
760 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
763 if (!ieee80211_sdata_running(sdata))
766 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
769 for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
770 struct ieee80211_bss_conf *link_conf =
771 rcu_dereference(sdata->vif.link_conf[link_id]);
776 if (rcu_access_pointer(link_conf->chanctx_conf) != conf)
780 compat = &link_conf->chandef;
782 compat = cfg80211_chandef_compatible(&link_conf->chandef,
784 if (WARN_ON_ONCE(!compat))
789 /* TDLS peers can sometimes affect the chandef width */
790 list_for_each_entry_rcu(sta, &local->sta_list, list) {
791 if (!sta->uploaded ||
792 !test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW) ||
793 !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
794 !sta->tdls_chandef.chan)
797 compat = cfg80211_chandef_compatible(&sta->tdls_chandef,
799 if (WARN_ON_ONCE(!compat))
807 ieee80211_change_chanctx(local, ctx, ctx, compat);
810 static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
811 struct ieee80211_chanctx *chanctx)
815 lockdep_assert_held(&local->chanctx_mtx);
816 /* for ieee80211_is_radar_required */
817 lockdep_assert_held(&local->mtx);
819 radar_enabled = ieee80211_chanctx_radar_required(local, chanctx);
821 if (radar_enabled == chanctx->conf.radar_enabled)
824 chanctx->conf.radar_enabled = radar_enabled;
826 if (!local->use_chanctx) {
827 local->hw.conf.radar_enabled = chanctx->conf.radar_enabled;
828 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
831 drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
834 static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
835 struct ieee80211_chanctx *new_ctx)
837 struct ieee80211_sub_if_data *sdata = link->sdata;
838 struct ieee80211_local *local = sdata->local;
839 struct ieee80211_chanctx_conf *conf;
840 struct ieee80211_chanctx *curr_ctx = NULL;
843 if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN))
846 conf = rcu_dereference_protected(link->conf->chanctx_conf,
847 lockdep_is_held(&local->chanctx_mtx));
850 curr_ctx = container_of(conf, struct ieee80211_chanctx, conf);
852 drv_unassign_vif_chanctx(local, sdata, link->conf, curr_ctx);
854 list_del(&link->assigned_chanctx_list);
858 ret = drv_assign_vif_chanctx(local, sdata, link->conf, new_ctx);
862 conf = &new_ctx->conf;
863 list_add(&link->assigned_chanctx_list,
864 &new_ctx->assigned_links);
868 rcu_assign_pointer(link->conf->chanctx_conf, conf);
870 sdata->vif.cfg.idle = !conf;
872 if (curr_ctx && ieee80211_chanctx_num_assigned(local, curr_ctx) > 0) {
873 ieee80211_recalc_chanctx_chantype(local, curr_ctx);
874 ieee80211_recalc_smps_chanctx(local, curr_ctx);
875 ieee80211_recalc_radar_chanctx(local, curr_ctx);
876 ieee80211_recalc_chanctx_min_def(local, curr_ctx);
879 if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) {
880 ieee80211_recalc_txpower(sdata, false);
881 ieee80211_recalc_chanctx_min_def(local, new_ctx);
884 if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
885 sdata->vif.type != NL80211_IFTYPE_MONITOR)
886 ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE);
888 ieee80211_check_fast_xmit_iface(sdata);
893 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
894 struct ieee80211_chanctx *chanctx)
896 struct ieee80211_sub_if_data *sdata;
897 u8 rx_chains_static, rx_chains_dynamic;
899 lockdep_assert_held(&local->chanctx_mtx);
901 rx_chains_static = 1;
902 rx_chains_dynamic = 1;
905 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
906 u8 needed_static, needed_dynamic;
907 unsigned int link_id;
909 if (!ieee80211_sdata_running(sdata))
912 switch (sdata->vif.type) {
913 case NL80211_IFTYPE_STATION:
914 if (!sdata->u.mgd.associated)
917 case NL80211_IFTYPE_AP:
918 case NL80211_IFTYPE_ADHOC:
919 case NL80211_IFTYPE_MESH_POINT:
920 case NL80211_IFTYPE_OCB:
926 for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
927 struct ieee80211_link_data *link;
929 link = rcu_dereference(sdata->link[link_id]);
934 if (rcu_access_pointer(link->conf->chanctx_conf) != &chanctx->conf)
937 switch (link->smps_mode) {
939 WARN_ONCE(1, "Invalid SMPS mode %d\n",
942 case IEEE80211_SMPS_OFF:
943 needed_static = link->needed_rx_chains;
944 needed_dynamic = link->needed_rx_chains;
946 case IEEE80211_SMPS_DYNAMIC:
948 needed_dynamic = link->needed_rx_chains;
950 case IEEE80211_SMPS_STATIC:
956 rx_chains_static = max(rx_chains_static, needed_static);
957 rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
961 /* Disable SMPS for the monitor interface */
962 sdata = rcu_dereference(local->monitor_sdata);
964 rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == &chanctx->conf)
965 rx_chains_dynamic = rx_chains_static = local->rx_chains;
969 if (!local->use_chanctx) {
970 if (rx_chains_static > 1)
971 local->smps_mode = IEEE80211_SMPS_OFF;
972 else if (rx_chains_dynamic > 1)
973 local->smps_mode = IEEE80211_SMPS_DYNAMIC;
975 local->smps_mode = IEEE80211_SMPS_STATIC;
976 ieee80211_hw_config(local, 0);
979 if (rx_chains_static == chanctx->conf.rx_chains_static &&
980 rx_chains_dynamic == chanctx->conf.rx_chains_dynamic)
983 chanctx->conf.rx_chains_static = rx_chains_static;
984 chanctx->conf.rx_chains_dynamic = rx_chains_dynamic;
985 drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
989 __ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
992 struct ieee80211_sub_if_data *sdata = link->sdata;
993 unsigned int link_id = link->link_id;
994 struct ieee80211_bss_conf *link_conf = link->conf;
995 struct ieee80211_local *local __maybe_unused = sdata->local;
996 struct ieee80211_sub_if_data *vlan;
997 struct ieee80211_chanctx_conf *conf;
999 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
1002 lockdep_assert_held(&local->mtx);
1004 /* Check that conf exists, even when clearing this function
1005 * must be called with the AP's channel context still there
1006 * as it would otherwise cause VLANs to have an invalid
1007 * channel context pointer for a while, possibly pointing
1008 * to a channel context that has already been freed.
1010 conf = rcu_dereference_protected(link_conf->chanctx_conf,
1011 lockdep_is_held(&local->chanctx_mtx));
1018 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
1019 struct ieee80211_bss_conf *vlan_conf;
1021 vlan_conf = rcu_dereference(vlan->vif.link_conf[link_id]);
1022 if (WARN_ON(!vlan_conf))
1025 rcu_assign_pointer(vlan_conf->chanctx_conf, conf);
1030 void ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
1033 struct ieee80211_local *local = link->sdata->local;
1035 mutex_lock(&local->chanctx_mtx);
1037 __ieee80211_link_copy_chanctx_to_vlans(link, clear);
1039 mutex_unlock(&local->chanctx_mtx);
1042 int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link)
1044 struct ieee80211_sub_if_data *sdata = link->sdata;
1045 struct ieee80211_chanctx *ctx = link->reserved_chanctx;
1047 lockdep_assert_held(&sdata->local->chanctx_mtx);
1052 list_del(&link->reserved_chanctx_list);
1053 link->reserved_chanctx = NULL;
1055 if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0) {
1056 if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
1057 if (WARN_ON(!ctx->replace_ctx))
1060 WARN_ON(ctx->replace_ctx->replace_state !=
1061 IEEE80211_CHANCTX_WILL_BE_REPLACED);
1062 WARN_ON(ctx->replace_ctx->replace_ctx != ctx);
1064 ctx->replace_ctx->replace_ctx = NULL;
1065 ctx->replace_ctx->replace_state =
1066 IEEE80211_CHANCTX_REPLACE_NONE;
1068 list_del_rcu(&ctx->list);
1069 kfree_rcu(ctx, rcu_head);
1071 ieee80211_free_chanctx(sdata->local, ctx);
1078 int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link,
1079 const struct cfg80211_chan_def *chandef,
1080 enum ieee80211_chanctx_mode mode,
1081 bool radar_required)
1083 struct ieee80211_sub_if_data *sdata = link->sdata;
1084 struct ieee80211_local *local = sdata->local;
1085 struct ieee80211_chanctx *new_ctx, *curr_ctx, *ctx;
1087 lockdep_assert_held(&local->chanctx_mtx);
1089 curr_ctx = ieee80211_link_get_chanctx(link);
1090 if (curr_ctx && local->use_chanctx && !local->ops->switch_vif_chanctx)
1093 new_ctx = ieee80211_find_reservation_chanctx(local, chandef, mode);
1095 if (ieee80211_can_create_new_chanctx(local)) {
1096 new_ctx = ieee80211_new_chanctx(local, chandef, mode);
1097 if (IS_ERR(new_ctx))
1098 return PTR_ERR(new_ctx);
1101 (curr_ctx->replace_state ==
1102 IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
1103 !list_empty(&curr_ctx->reserved_links)) {
1105 * Another link already requested this context
1106 * for a reservation. Find another one hoping
1107 * all links assigned to it will also switch
1110 * TODO: This needs a little more work as some
1111 * cases (more than 2 chanctx capable devices)
1112 * may fail which could otherwise succeed
1113 * provided some channel context juggling was
1116 * Consider ctx1..3, link1..6, each ctx has 2
1117 * links. link1 and link2 from ctx1 request new
1118 * different chandefs starting 2 in-place
1119 * reserations with ctx4 and ctx5 replacing
1120 * ctx1 and ctx2 respectively. Next link5 and
1121 * link6 from ctx3 reserve ctx4. If link3 and
1122 * link4 remain on ctx2 as they are then this
1123 * fails unless `replace_ctx` from ctx5 is
1124 * replaced with ctx3.
1126 list_for_each_entry(ctx, &local->chanctx_list,
1128 if (ctx->replace_state !=
1129 IEEE80211_CHANCTX_REPLACE_NONE)
1132 if (!list_empty(&ctx->reserved_links))
1141 * If that's true then all available contexts already
1142 * have reservations and cannot be used.
1145 (curr_ctx->replace_state ==
1146 IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
1147 !list_empty(&curr_ctx->reserved_links))
1150 new_ctx = ieee80211_alloc_chanctx(local, chandef, mode);
1154 new_ctx->replace_ctx = curr_ctx;
1155 new_ctx->replace_state =
1156 IEEE80211_CHANCTX_REPLACES_OTHER;
1158 curr_ctx->replace_ctx = new_ctx;
1159 curr_ctx->replace_state =
1160 IEEE80211_CHANCTX_WILL_BE_REPLACED;
1162 list_add_rcu(&new_ctx->list, &local->chanctx_list);
1166 list_add(&link->reserved_chanctx_list, &new_ctx->reserved_links);
1167 link->reserved_chanctx = new_ctx;
1168 link->reserved_chandef = *chandef;
1169 link->reserved_radar_required = radar_required;
1170 link->reserved_ready = false;
1176 ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link)
1178 struct ieee80211_sub_if_data *sdata = link->sdata;
1180 switch (sdata->vif.type) {
1181 case NL80211_IFTYPE_ADHOC:
1182 case NL80211_IFTYPE_AP:
1183 case NL80211_IFTYPE_MESH_POINT:
1184 case NL80211_IFTYPE_OCB:
1185 ieee80211_queue_work(&sdata->local->hw,
1186 &link->csa_finalize_work);
1188 case NL80211_IFTYPE_STATION:
1189 ieee80211_queue_work(&sdata->local->hw,
1190 &link->u.mgd.chswitch_work);
1192 case NL80211_IFTYPE_UNSPECIFIED:
1193 case NL80211_IFTYPE_AP_VLAN:
1194 case NL80211_IFTYPE_WDS:
1195 case NL80211_IFTYPE_MONITOR:
1196 case NL80211_IFTYPE_P2P_CLIENT:
1197 case NL80211_IFTYPE_P2P_GO:
1198 case NL80211_IFTYPE_P2P_DEVICE:
1199 case NL80211_IFTYPE_NAN:
1200 case NUM_NL80211_IFTYPES:
1207 ieee80211_link_update_chandef(struct ieee80211_link_data *link,
1208 const struct cfg80211_chan_def *chandef)
1210 struct ieee80211_sub_if_data *sdata = link->sdata;
1211 unsigned int link_id = link->link_id;
1212 struct ieee80211_sub_if_data *vlan;
1214 link->conf->chandef = *chandef;
1216 if (sdata->vif.type != NL80211_IFTYPE_AP)
1220 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
1221 struct ieee80211_bss_conf *vlan_conf;
1223 vlan_conf = rcu_dereference(vlan->vif.link_conf[link_id]);
1224 if (WARN_ON(!vlan_conf))
1227 vlan_conf->chandef = *chandef;
1233 ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)
1235 struct ieee80211_sub_if_data *sdata = link->sdata;
1236 struct ieee80211_bss_conf *link_conf = link->conf;
1237 struct ieee80211_local *local = sdata->local;
1238 struct ieee80211_vif_chanctx_switch vif_chsw[1] = {};
1239 struct ieee80211_chanctx *old_ctx, *new_ctx;
1240 const struct cfg80211_chan_def *chandef;
1244 lockdep_assert_held(&local->mtx);
1245 lockdep_assert_held(&local->chanctx_mtx);
1247 new_ctx = link->reserved_chanctx;
1248 old_ctx = ieee80211_link_get_chanctx(link);
1250 if (WARN_ON(!link->reserved_ready))
1253 if (WARN_ON(!new_ctx))
1256 if (WARN_ON(!old_ctx))
1259 if (WARN_ON(new_ctx->replace_state ==
1260 IEEE80211_CHANCTX_REPLACES_OTHER))
1263 chandef = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
1264 &link->reserved_chandef);
1265 if (WARN_ON(!chandef))
1268 if (link_conf->chandef.width != link->reserved_chandef.width)
1269 changed = BSS_CHANGED_BANDWIDTH;
1271 ieee80211_link_update_chandef(link, &link->reserved_chandef);
1273 ieee80211_change_chanctx(local, new_ctx, old_ctx, chandef);
1275 vif_chsw[0].vif = &sdata->vif;
1276 vif_chsw[0].old_ctx = &old_ctx->conf;
1277 vif_chsw[0].new_ctx = &new_ctx->conf;
1278 vif_chsw[0].link_conf = link->conf;
1280 list_del(&link->reserved_chanctx_list);
1281 link->reserved_chanctx = NULL;
1283 err = drv_switch_vif_chanctx(local, vif_chsw, 1,
1284 CHANCTX_SWMODE_REASSIGN_VIF);
1286 if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
1287 ieee80211_free_chanctx(local, new_ctx);
1292 list_move(&link->assigned_chanctx_list, &new_ctx->assigned_links);
1293 rcu_assign_pointer(link_conf->chanctx_conf, &new_ctx->conf);
1295 if (sdata->vif.type == NL80211_IFTYPE_AP)
1296 __ieee80211_link_copy_chanctx_to_vlans(link, false);
1298 ieee80211_check_fast_xmit_iface(sdata);
1300 if (ieee80211_chanctx_refcount(local, old_ctx) == 0)
1301 ieee80211_free_chanctx(local, old_ctx);
1303 ieee80211_recalc_chanctx_min_def(local, new_ctx);
1304 ieee80211_recalc_smps_chanctx(local, new_ctx);
1305 ieee80211_recalc_radar_chanctx(local, new_ctx);
1308 ieee80211_link_info_change_notify(sdata, link, changed);
1311 ieee80211_link_chanctx_reservation_complete(link);
1316 ieee80211_link_use_reserved_assign(struct ieee80211_link_data *link)
1318 struct ieee80211_sub_if_data *sdata = link->sdata;
1319 struct ieee80211_local *local = sdata->local;
1320 struct ieee80211_chanctx *old_ctx, *new_ctx;
1321 const struct cfg80211_chan_def *chandef;
1324 old_ctx = ieee80211_link_get_chanctx(link);
1325 new_ctx = link->reserved_chanctx;
1327 if (WARN_ON(!link->reserved_ready))
1330 if (WARN_ON(old_ctx))
1333 if (WARN_ON(!new_ctx))
1336 if (WARN_ON(new_ctx->replace_state ==
1337 IEEE80211_CHANCTX_REPLACES_OTHER))
1340 chandef = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
1341 &link->reserved_chandef);
1342 if (WARN_ON(!chandef))
1345 ieee80211_change_chanctx(local, new_ctx, new_ctx, chandef);
1347 list_del(&link->reserved_chanctx_list);
1348 link->reserved_chanctx = NULL;
1350 err = ieee80211_assign_link_chanctx(link, new_ctx);
1352 if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
1353 ieee80211_free_chanctx(local, new_ctx);
1359 ieee80211_link_chanctx_reservation_complete(link);
1364 ieee80211_link_has_in_place_reservation(struct ieee80211_link_data *link)
1366 struct ieee80211_sub_if_data *sdata = link->sdata;
1367 struct ieee80211_chanctx *old_ctx, *new_ctx;
1369 lockdep_assert_held(&sdata->local->chanctx_mtx);
1371 new_ctx = link->reserved_chanctx;
1372 old_ctx = ieee80211_link_get_chanctx(link);
1377 if (WARN_ON(!new_ctx))
1380 if (old_ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
1383 if (new_ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1389 static int ieee80211_chsw_switch_hwconf(struct ieee80211_local *local,
1390 struct ieee80211_chanctx *new_ctx)
1392 const struct cfg80211_chan_def *chandef;
1394 lockdep_assert_held(&local->mtx);
1395 lockdep_assert_held(&local->chanctx_mtx);
1397 chandef = ieee80211_chanctx_reserved_chandef(local, new_ctx, NULL);
1398 if (WARN_ON(!chandef))
1401 local->hw.conf.radar_enabled = new_ctx->conf.radar_enabled;
1402 local->_oper_chandef = *chandef;
1403 ieee80211_hw_config(local, 0);
1408 static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local,
1411 struct ieee80211_vif_chanctx_switch *vif_chsw;
1412 struct ieee80211_link_data *link;
1413 struct ieee80211_chanctx *ctx, *old_ctx;
1416 lockdep_assert_held(&local->mtx);
1417 lockdep_assert_held(&local->chanctx_mtx);
1419 vif_chsw = kcalloc(n_vifs, sizeof(vif_chsw[0]), GFP_KERNEL);
1424 list_for_each_entry(ctx, &local->chanctx_list, list) {
1425 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1428 if (WARN_ON(!ctx->replace_ctx)) {
1433 list_for_each_entry(link, &ctx->reserved_links,
1434 reserved_chanctx_list) {
1435 if (!ieee80211_link_has_in_place_reservation(link))
1438 old_ctx = ieee80211_link_get_chanctx(link);
1439 vif_chsw[i].vif = &link->sdata->vif;
1440 vif_chsw[i].old_ctx = &old_ctx->conf;
1441 vif_chsw[i].new_ctx = &ctx->conf;
1442 vif_chsw[i].link_conf = link->conf;
1448 err = drv_switch_vif_chanctx(local, vif_chsw, n_vifs,
1449 CHANCTX_SWMODE_SWAP_CONTEXTS);
1456 static int ieee80211_chsw_switch_ctxs(struct ieee80211_local *local)
1458 struct ieee80211_chanctx *ctx;
1461 lockdep_assert_held(&local->mtx);
1462 lockdep_assert_held(&local->chanctx_mtx);
1464 list_for_each_entry(ctx, &local->chanctx_list, list) {
1465 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1468 if (!list_empty(&ctx->replace_ctx->assigned_links))
1471 ieee80211_del_chanctx(local, ctx->replace_ctx);
1472 err = ieee80211_add_chanctx(local, ctx);
1480 WARN_ON(ieee80211_add_chanctx(local, ctx));
1481 list_for_each_entry_continue_reverse(ctx, &local->chanctx_list, list) {
1482 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1485 if (!list_empty(&ctx->replace_ctx->assigned_links))
1488 ieee80211_del_chanctx(local, ctx);
1489 WARN_ON(ieee80211_add_chanctx(local, ctx->replace_ctx));
1495 static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
1497 struct ieee80211_chanctx *ctx, *ctx_tmp, *old_ctx;
1498 struct ieee80211_chanctx *new_ctx = NULL;
1499 int err, n_assigned, n_reserved, n_ready;
1500 int n_ctx = 0, n_vifs_switch = 0, n_vifs_assign = 0, n_vifs_ctxless = 0;
1502 lockdep_assert_held(&local->mtx);
1503 lockdep_assert_held(&local->chanctx_mtx);
1506 * If there are 2 independent pairs of channel contexts performing
1507 * cross-switch of their vifs this code will still wait until both are
1508 * ready even though it could be possible to switch one before the
1511 * For practical reasons and code simplicity just do a single huge
1516 * Verify if the reservation is still feasible.
1517 * - if it's not then disconnect
1518 * - if it is but not all vifs necessary are ready then defer
1521 list_for_each_entry(ctx, &local->chanctx_list, list) {
1522 struct ieee80211_link_data *link;
1524 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1527 if (WARN_ON(!ctx->replace_ctx)) {
1532 if (!local->use_chanctx)
1541 list_for_each_entry(link, &ctx->replace_ctx->assigned_links,
1542 assigned_chanctx_list) {
1544 if (link->reserved_chanctx) {
1546 if (link->reserved_ready)
1551 if (n_assigned != n_reserved) {
1552 if (n_ready == n_reserved) {
1553 wiphy_info(local->hw.wiphy,
1554 "channel context reservation cannot be finalized because some interfaces aren't switching\n");
1562 ctx->conf.radar_enabled = false;
1563 list_for_each_entry(link, &ctx->reserved_links,
1564 reserved_chanctx_list) {
1565 if (ieee80211_link_has_in_place_reservation(link) &&
1566 !link->reserved_ready)
1569 old_ctx = ieee80211_link_get_chanctx(link);
1571 if (old_ctx->replace_state ==
1572 IEEE80211_CHANCTX_WILL_BE_REPLACED)
1580 if (link->reserved_radar_required)
1581 ctx->conf.radar_enabled = true;
1585 if (WARN_ON(n_ctx == 0) ||
1586 WARN_ON(n_vifs_switch == 0 &&
1587 n_vifs_assign == 0 &&
1588 n_vifs_ctxless == 0) ||
1589 WARN_ON(n_ctx > 1 && !local->use_chanctx) ||
1590 WARN_ON(!new_ctx && !local->use_chanctx)) {
1596 * All necessary vifs are ready. Perform the switch now depending on
1597 * reservations and driver capabilities.
1600 if (local->use_chanctx) {
1601 if (n_vifs_switch > 0) {
1602 err = ieee80211_chsw_switch_vifs(local, n_vifs_switch);
1607 if (n_vifs_assign > 0 || n_vifs_ctxless > 0) {
1608 err = ieee80211_chsw_switch_ctxs(local);
1613 err = ieee80211_chsw_switch_hwconf(local, new_ctx);
1619 * Update all structures, values and pointers to point to new channel
1622 list_for_each_entry(ctx, &local->chanctx_list, list) {
1623 struct ieee80211_link_data *link, *link_tmp;
1625 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1628 if (WARN_ON(!ctx->replace_ctx)) {
1633 list_for_each_entry(link, &ctx->reserved_links,
1634 reserved_chanctx_list) {
1635 struct ieee80211_sub_if_data *sdata = link->sdata;
1636 struct ieee80211_bss_conf *link_conf = link->conf;
1639 if (!ieee80211_link_has_in_place_reservation(link))
1642 rcu_assign_pointer(link_conf->chanctx_conf,
1645 if (sdata->vif.type == NL80211_IFTYPE_AP)
1646 __ieee80211_link_copy_chanctx_to_vlans(link,
1649 ieee80211_check_fast_xmit_iface(sdata);
1651 link->radar_required = link->reserved_radar_required;
1653 if (link_conf->chandef.width != link->reserved_chandef.width)
1654 changed = BSS_CHANGED_BANDWIDTH;
1656 ieee80211_link_update_chandef(link, &link->reserved_chandef);
1658 ieee80211_link_info_change_notify(sdata,
1662 ieee80211_recalc_txpower(sdata, false);
1665 ieee80211_recalc_chanctx_chantype(local, ctx);
1666 ieee80211_recalc_smps_chanctx(local, ctx);
1667 ieee80211_recalc_radar_chanctx(local, ctx);
1668 ieee80211_recalc_chanctx_min_def(local, ctx);
1670 list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
1671 reserved_chanctx_list) {
1672 if (ieee80211_link_get_chanctx(link) != ctx)
1675 list_del(&link->reserved_chanctx_list);
1676 list_move(&link->assigned_chanctx_list,
1677 &ctx->assigned_links);
1678 link->reserved_chanctx = NULL;
1680 ieee80211_link_chanctx_reservation_complete(link);
1684 * This context might have been a dependency for an already
1685 * ready re-assign reservation interface that was deferred. Do
1686 * not propagate error to the caller though. The in-place
1687 * reservation for originally requested interface has already
1688 * succeeded at this point.
1690 list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
1691 reserved_chanctx_list) {
1692 if (WARN_ON(ieee80211_link_has_in_place_reservation(link)))
1695 if (WARN_ON(link->reserved_chanctx != ctx))
1698 if (!link->reserved_ready)
1701 if (ieee80211_link_get_chanctx(link))
1702 err = ieee80211_link_use_reserved_reassign(link);
1704 err = ieee80211_link_use_reserved_assign(link);
1708 "failed to finalize (re-)assign reservation (err=%d)\n",
1710 ieee80211_link_unreserve_chanctx(link);
1711 cfg80211_stop_iface(local->hw.wiphy,
1719 * Finally free old contexts
1722 list_for_each_entry_safe(ctx, ctx_tmp, &local->chanctx_list, list) {
1723 if (ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
1726 ctx->replace_ctx->replace_ctx = NULL;
1727 ctx->replace_ctx->replace_state =
1728 IEEE80211_CHANCTX_REPLACE_NONE;
1730 list_del_rcu(&ctx->list);
1731 kfree_rcu(ctx, rcu_head);
1737 list_for_each_entry(ctx, &local->chanctx_list, list) {
1738 struct ieee80211_link_data *link, *link_tmp;
1740 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1743 list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
1744 reserved_chanctx_list) {
1745 ieee80211_link_unreserve_chanctx(link);
1746 ieee80211_link_chanctx_reservation_complete(link);
1753 static void __ieee80211_link_release_channel(struct ieee80211_link_data *link)
1755 struct ieee80211_sub_if_data *sdata = link->sdata;
1756 struct ieee80211_bss_conf *link_conf = link->conf;
1757 struct ieee80211_local *local = sdata->local;
1758 struct ieee80211_chanctx_conf *conf;
1759 struct ieee80211_chanctx *ctx;
1760 bool use_reserved_switch = false;
1762 lockdep_assert_held(&local->chanctx_mtx);
1764 conf = rcu_dereference_protected(link_conf->chanctx_conf,
1765 lockdep_is_held(&local->chanctx_mtx));
1769 ctx = container_of(conf, struct ieee80211_chanctx, conf);
1771 if (link->reserved_chanctx) {
1772 if (link->reserved_chanctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER &&
1773 ieee80211_chanctx_num_reserved(local, link->reserved_chanctx) > 1)
1774 use_reserved_switch = true;
1776 ieee80211_link_unreserve_chanctx(link);
1779 ieee80211_assign_link_chanctx(link, NULL);
1780 if (ieee80211_chanctx_refcount(local, ctx) == 0)
1781 ieee80211_free_chanctx(local, ctx);
1783 link->radar_required = false;
1785 /* Unreserving may ready an in-place reservation. */
1786 if (use_reserved_switch)
1787 ieee80211_vif_use_reserved_switch(local);
1790 int ieee80211_link_use_channel(struct ieee80211_link_data *link,
1791 const struct cfg80211_chan_def *chandef,
1792 enum ieee80211_chanctx_mode mode)
1794 struct ieee80211_sub_if_data *sdata = link->sdata;
1795 struct ieee80211_local *local = sdata->local;
1796 struct ieee80211_chanctx *ctx;
1797 u8 radar_detect_width = 0;
1800 lockdep_assert_held(&local->mtx);
1802 if (sdata->vif.active_links &&
1803 !(sdata->vif.active_links & BIT(link->link_id))) {
1804 ieee80211_link_update_chandef(link, chandef);
1808 mutex_lock(&local->chanctx_mtx);
1810 ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
1812 sdata->wdev.iftype);
1816 radar_detect_width = BIT(chandef->width);
1818 link->radar_required = ret;
1820 ret = ieee80211_check_combinations(sdata, chandef, mode,
1821 radar_detect_width);
1825 __ieee80211_link_release_channel(link);
1827 ctx = ieee80211_find_chanctx(local, chandef, mode);
1829 ctx = ieee80211_new_chanctx(local, chandef, mode);
1835 ieee80211_link_update_chandef(link, chandef);
1837 ret = ieee80211_assign_link_chanctx(link, ctx);
1839 /* if assign fails refcount stays the same */
1840 if (ieee80211_chanctx_refcount(local, ctx) == 0)
1841 ieee80211_free_chanctx(local, ctx);
1845 ieee80211_recalc_smps_chanctx(local, ctx);
1846 ieee80211_recalc_radar_chanctx(local, ctx);
1849 link->radar_required = false;
1851 mutex_unlock(&local->chanctx_mtx);
1855 int ieee80211_link_use_reserved_context(struct ieee80211_link_data *link)
1857 struct ieee80211_sub_if_data *sdata = link->sdata;
1858 struct ieee80211_local *local = sdata->local;
1859 struct ieee80211_chanctx *new_ctx;
1860 struct ieee80211_chanctx *old_ctx;
1863 lockdep_assert_held(&local->mtx);
1864 lockdep_assert_held(&local->chanctx_mtx);
1866 new_ctx = link->reserved_chanctx;
1867 old_ctx = ieee80211_link_get_chanctx(link);
1869 if (WARN_ON(!new_ctx))
1872 if (WARN_ON(new_ctx->replace_state ==
1873 IEEE80211_CHANCTX_WILL_BE_REPLACED))
1876 if (WARN_ON(link->reserved_ready))
1879 link->reserved_ready = true;
1881 if (new_ctx->replace_state == IEEE80211_CHANCTX_REPLACE_NONE) {
1883 return ieee80211_link_use_reserved_reassign(link);
1885 return ieee80211_link_use_reserved_assign(link);
1889 * In-place reservation may need to be finalized now either if:
1890 * a) sdata is taking part in the swapping itself and is the last one
1891 * b) sdata has switched with a re-assign reservation to an existing
1892 * context readying in-place switching of old_ctx
1894 * In case of (b) do not propagate the error up because the requested
1895 * sdata already switched successfully. Just spill an extra warning.
1896 * The ieee80211_vif_use_reserved_switch() already stops all necessary
1897 * interfaces upon failure.
1900 old_ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
1901 new_ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
1902 err = ieee80211_vif_use_reserved_switch(local);
1903 if (err && err != -EAGAIN) {
1904 if (new_ctx->replace_state ==
1905 IEEE80211_CHANCTX_REPLACES_OTHER)
1908 wiphy_info(local->hw.wiphy,
1909 "depending in-place reservation failed (err=%d)\n",
1917 int ieee80211_link_change_bandwidth(struct ieee80211_link_data *link,
1918 const struct cfg80211_chan_def *chandef,
1921 struct ieee80211_sub_if_data *sdata = link->sdata;
1922 struct ieee80211_bss_conf *link_conf = link->conf;
1923 struct ieee80211_local *local = sdata->local;
1924 struct ieee80211_chanctx_conf *conf;
1925 struct ieee80211_chanctx *ctx;
1926 const struct cfg80211_chan_def *compat;
1929 if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
1930 IEEE80211_CHAN_DISABLED))
1933 mutex_lock(&local->chanctx_mtx);
1934 if (cfg80211_chandef_identical(chandef, &link_conf->chandef)) {
1939 if (chandef->width == NL80211_CHAN_WIDTH_20_NOHT ||
1940 link_conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT) {
1945 conf = rcu_dereference_protected(link_conf->chanctx_conf,
1946 lockdep_is_held(&local->chanctx_mtx));
1952 ctx = container_of(conf, struct ieee80211_chanctx, conf);
1954 compat = cfg80211_chandef_compatible(&conf->def, chandef);
1960 switch (ctx->replace_state) {
1961 case IEEE80211_CHANCTX_REPLACE_NONE:
1962 if (!ieee80211_chanctx_reserved_chandef(local, ctx, compat)) {
1967 case IEEE80211_CHANCTX_WILL_BE_REPLACED:
1968 /* TODO: Perhaps the bandwidth change could be treated as a
1969 * reservation itself? */
1972 case IEEE80211_CHANCTX_REPLACES_OTHER:
1973 /* channel context that is going to replace another channel
1974 * context doesn't really exist and shouldn't be assigned
1980 ieee80211_link_update_chandef(link, chandef);
1982 ieee80211_recalc_chanctx_chantype(local, ctx);
1984 *changed |= BSS_CHANGED_BANDWIDTH;
1987 mutex_unlock(&local->chanctx_mtx);
1991 void ieee80211_link_release_channel(struct ieee80211_link_data *link)
1993 struct ieee80211_sub_if_data *sdata = link->sdata;
1995 mutex_lock(&sdata->local->chanctx_mtx);
1996 if (rcu_access_pointer(link->conf->chanctx_conf)) {
1997 lockdep_assert_held(&sdata->local->mtx);
1998 __ieee80211_link_release_channel(link);
2000 mutex_unlock(&sdata->local->chanctx_mtx);
2003 void ieee80211_link_vlan_copy_chanctx(struct ieee80211_link_data *link)
2005 struct ieee80211_sub_if_data *sdata = link->sdata;
2006 unsigned int link_id = link->link_id;
2007 struct ieee80211_bss_conf *link_conf = link->conf;
2008 struct ieee80211_bss_conf *ap_conf;
2009 struct ieee80211_local *local = sdata->local;
2010 struct ieee80211_sub_if_data *ap;
2011 struct ieee80211_chanctx_conf *conf;
2013 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
2016 ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
2018 mutex_lock(&local->chanctx_mtx);
2021 ap_conf = rcu_dereference(ap->vif.link_conf[link_id]);
2022 conf = rcu_dereference_protected(ap_conf->chanctx_conf,
2023 lockdep_is_held(&local->chanctx_mtx));
2024 rcu_assign_pointer(link_conf->chanctx_conf, conf);
2026 mutex_unlock(&local->chanctx_mtx);
2029 void ieee80211_iter_chan_contexts_atomic(
2030 struct ieee80211_hw *hw,
2031 void (*iter)(struct ieee80211_hw *hw,
2032 struct ieee80211_chanctx_conf *chanctx_conf,
2036 struct ieee80211_local *local = hw_to_local(hw);
2037 struct ieee80211_chanctx *ctx;
2040 list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
2041 if (ctx->driver_present)
2042 iter(hw, &ctx->conf, iter_data);
2045 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);