2 * mac80211 - channel management
5 #include <linux/nl80211.h>
6 #include <linux/export.h>
7 #include <linux/rtnetlink.h>
8 #include <net/cfg80211.h>
9 #include "ieee80211_i.h"
10 #include "driver-ops.h"
12 static int ieee80211_num_chanctx(struct ieee80211_local
*local
)
14 struct ieee80211_chanctx
*ctx
;
17 lockdep_assert_held(&local
->chanctx_mtx
);
19 list_for_each_entry(ctx
, &local
->chanctx_list
, list
)
25 static bool ieee80211_can_create_new_chanctx(struct ieee80211_local
*local
)
27 lockdep_assert_held(&local
->chanctx_mtx
);
28 return ieee80211_num_chanctx(local
) < ieee80211_max_num_channels(local
);
31 static enum nl80211_chan_width
ieee80211_get_sta_bw(struct ieee80211_sta
*sta
)
33 switch (sta
->bandwidth
) {
34 case IEEE80211_STA_RX_BW_20
:
35 if (sta
->ht_cap
.ht_supported
)
36 return NL80211_CHAN_WIDTH_20
;
38 return NL80211_CHAN_WIDTH_20_NOHT
;
39 case IEEE80211_STA_RX_BW_40
:
40 return NL80211_CHAN_WIDTH_40
;
41 case IEEE80211_STA_RX_BW_80
:
42 return NL80211_CHAN_WIDTH_80
;
43 case IEEE80211_STA_RX_BW_160
:
45 * This applied for both 160 and 80+80. since we use
46 * the returned value to consider degradation of
47 * ctx->conf.min_def, we have to make sure to take
48 * the bigger one (NL80211_CHAN_WIDTH_160).
49 * Otherwise we might try degrading even when not
50 * needed, as the max required sta_bw returned (80+80)
51 * might be smaller than the configured bw (160).
53 return NL80211_CHAN_WIDTH_160
;
56 return NL80211_CHAN_WIDTH_20
;
60 static enum nl80211_chan_width
61 ieee80211_get_max_required_bw(struct ieee80211_sub_if_data
*sdata
)
63 enum nl80211_chan_width max_bw
= NL80211_CHAN_WIDTH_20_NOHT
;
67 list_for_each_entry_rcu(sta
, &sdata
->local
->sta_list
, list
) {
68 if (sdata
!= sta
->sdata
&&
69 !(sta
->sdata
->bss
&& sta
->sdata
->bss
== sdata
->bss
))
75 max_bw
= max(max_bw
, ieee80211_get_sta_bw(&sta
->sta
));
82 static enum nl80211_chan_width
83 ieee80211_get_chanctx_max_required_bw(struct ieee80211_local
*local
,
84 struct ieee80211_chanctx_conf
*conf
)
86 struct ieee80211_sub_if_data
*sdata
;
87 enum nl80211_chan_width max_bw
= NL80211_CHAN_WIDTH_20_NOHT
;
90 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
91 struct ieee80211_vif
*vif
= &sdata
->vif
;
92 enum nl80211_chan_width width
= NL80211_CHAN_WIDTH_20_NOHT
;
94 if (!ieee80211_sdata_running(sdata
))
97 if (rcu_access_pointer(sdata
->vif
.chanctx_conf
) != conf
)
101 case NL80211_IFTYPE_AP
:
102 case NL80211_IFTYPE_AP_VLAN
:
103 width
= ieee80211_get_max_required_bw(sdata
);
105 case NL80211_IFTYPE_P2P_DEVICE
:
107 case NL80211_IFTYPE_STATION
:
108 case NL80211_IFTYPE_ADHOC
:
109 case NL80211_IFTYPE_WDS
:
110 case NL80211_IFTYPE_MESH_POINT
:
111 width
= vif
->bss_conf
.chandef
.width
;
113 case NL80211_IFTYPE_UNSPECIFIED
:
114 case NUM_NL80211_IFTYPES
:
115 case NL80211_IFTYPE_MONITOR
:
116 case NL80211_IFTYPE_P2P_CLIENT
:
117 case NL80211_IFTYPE_P2P_GO
:
120 max_bw
= max(max_bw
, width
);
123 /* use the configured bandwidth in case of monitor interface */
124 sdata
= rcu_dereference(local
->monitor_sdata
);
125 if (sdata
&& rcu_access_pointer(sdata
->vif
.chanctx_conf
) == conf
)
126 max_bw
= max(max_bw
, conf
->def
.width
);
134 * recalc the min required chan width of the channel context, which is
135 * the max of min required widths of all the interfaces bound to this
138 void ieee80211_recalc_chanctx_min_def(struct ieee80211_local
*local
,
139 struct ieee80211_chanctx
*ctx
)
141 enum nl80211_chan_width max_bw
;
142 struct cfg80211_chan_def min_def
;
144 lockdep_assert_held(&local
->chanctx_mtx
);
146 /* don't optimize 5MHz, 10MHz, and radar_enabled confs */
147 if (ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_5
||
148 ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_10
||
149 ctx
->conf
.radar_enabled
) {
150 ctx
->conf
.min_def
= ctx
->conf
.def
;
154 max_bw
= ieee80211_get_chanctx_max_required_bw(local
, &ctx
->conf
);
156 /* downgrade chandef up to max_bw */
157 min_def
= ctx
->conf
.def
;
158 while (min_def
.width
> max_bw
)
159 ieee80211_chandef_downgrade(&min_def
);
161 if (cfg80211_chandef_identical(&ctx
->conf
.min_def
, &min_def
))
164 ctx
->conf
.min_def
= min_def
;
165 if (!ctx
->driver_present
)
168 drv_change_chanctx(local
, ctx
, IEEE80211_CHANCTX_CHANGE_MIN_WIDTH
);
171 static void ieee80211_change_chanctx(struct ieee80211_local
*local
,
172 struct ieee80211_chanctx
*ctx
,
173 const struct cfg80211_chan_def
*chandef
)
175 if (cfg80211_chandef_identical(&ctx
->conf
.def
, chandef
))
178 WARN_ON(!cfg80211_chandef_compatible(&ctx
->conf
.def
, chandef
));
180 ctx
->conf
.def
= *chandef
;
181 drv_change_chanctx(local
, ctx
, IEEE80211_CHANCTX_CHANGE_WIDTH
);
182 ieee80211_recalc_chanctx_min_def(local
, ctx
);
184 if (!local
->use_chanctx
) {
185 local
->_oper_chandef
= *chandef
;
186 ieee80211_hw_config(local
, 0);
190 static bool ieee80211_chanctx_is_reserved(struct ieee80211_local
*local
,
191 struct ieee80211_chanctx
*ctx
)
193 struct ieee80211_sub_if_data
*sdata
;
196 lockdep_assert_held(&local
->chanctx_mtx
);
198 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
199 if (!ieee80211_sdata_running(sdata
))
201 if (sdata
->reserved_chanctx
== ctx
) {
211 static struct ieee80211_chanctx
*
212 ieee80211_find_chanctx(struct ieee80211_local
*local
,
213 const struct cfg80211_chan_def
*chandef
,
214 enum ieee80211_chanctx_mode mode
)
216 struct ieee80211_chanctx
*ctx
;
218 lockdep_assert_held(&local
->chanctx_mtx
);
220 if (mode
== IEEE80211_CHANCTX_EXCLUSIVE
)
223 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
224 const struct cfg80211_chan_def
*compat
;
226 /* We don't support chanctx reservation for multiple
227 * vifs yet, so don't allow reserved chanctxs to be
230 if ((ctx
->mode
== IEEE80211_CHANCTX_EXCLUSIVE
) ||
231 ieee80211_chanctx_is_reserved(local
, ctx
))
234 compat
= cfg80211_chandef_compatible(&ctx
->conf
.def
, chandef
);
238 ieee80211_change_chanctx(local
, ctx
, compat
);
246 static bool ieee80211_is_radar_required(struct ieee80211_local
*local
)
248 struct ieee80211_sub_if_data
*sdata
;
250 lockdep_assert_held(&local
->mtx
);
253 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
254 if (sdata
->radar_required
) {
264 static struct ieee80211_chanctx
*
265 ieee80211_new_chanctx(struct ieee80211_local
*local
,
266 const struct cfg80211_chan_def
*chandef
,
267 enum ieee80211_chanctx_mode mode
)
269 struct ieee80211_chanctx
*ctx
;
273 lockdep_assert_held(&local
->chanctx_mtx
);
275 ctx
= kzalloc(sizeof(*ctx
) + local
->hw
.chanctx_data_size
, GFP_KERNEL
);
277 return ERR_PTR(-ENOMEM
);
279 INIT_LIST_HEAD(&ctx
->assigned_vifs
);
280 ctx
->conf
.def
= *chandef
;
281 ctx
->conf
.rx_chains_static
= 1;
282 ctx
->conf
.rx_chains_dynamic
= 1;
284 ctx
->conf
.radar_enabled
= ieee80211_is_radar_required(local
);
285 ieee80211_recalc_chanctx_min_def(local
, ctx
);
286 if (!local
->use_chanctx
)
287 local
->hw
.conf
.radar_enabled
= ctx
->conf
.radar_enabled
;
289 /* we hold the mutex to prevent idle from changing */
290 lockdep_assert_held(&local
->mtx
);
291 /* turn idle off *before* setting channel -- some drivers need that */
292 changed
= ieee80211_idle_off(local
);
294 ieee80211_hw_config(local
, changed
);
296 if (!local
->use_chanctx
) {
297 local
->_oper_chandef
= *chandef
;
298 ieee80211_hw_config(local
, 0);
300 err
= drv_add_chanctx(local
, ctx
);
303 ieee80211_recalc_idle(local
);
308 /* and keep the mutex held until the new chanctx is on the list */
309 list_add_rcu(&ctx
->list
, &local
->chanctx_list
);
314 static void ieee80211_free_chanctx(struct ieee80211_local
*local
,
315 struct ieee80211_chanctx
*ctx
)
317 bool check_single_channel
= false;
318 lockdep_assert_held(&local
->chanctx_mtx
);
320 WARN_ON_ONCE(ctx
->refcount
!= 0);
322 if (!local
->use_chanctx
) {
323 struct cfg80211_chan_def
*chandef
= &local
->_oper_chandef
;
324 chandef
->width
= NL80211_CHAN_WIDTH_20_NOHT
;
325 chandef
->center_freq1
= chandef
->chan
->center_freq
;
326 chandef
->center_freq2
= 0;
328 /* NOTE: Disabling radar is only valid here for
329 * single channel context. To be sure, check it ...
331 if (local
->hw
.conf
.radar_enabled
)
332 check_single_channel
= true;
333 local
->hw
.conf
.radar_enabled
= false;
335 ieee80211_hw_config(local
, 0);
337 drv_remove_chanctx(local
, ctx
);
340 list_del_rcu(&ctx
->list
);
341 kfree_rcu(ctx
, rcu_head
);
343 /* throw a warning if this wasn't the only channel context. */
344 WARN_ON(check_single_channel
&& !list_empty(&local
->chanctx_list
));
346 ieee80211_recalc_idle(local
);
349 static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local
*local
,
350 struct ieee80211_chanctx
*ctx
)
352 struct ieee80211_chanctx_conf
*conf
= &ctx
->conf
;
353 struct ieee80211_sub_if_data
*sdata
;
354 const struct cfg80211_chan_def
*compat
= NULL
;
356 lockdep_assert_held(&local
->chanctx_mtx
);
359 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
361 if (!ieee80211_sdata_running(sdata
))
363 if (rcu_access_pointer(sdata
->vif
.chanctx_conf
) != conf
)
367 compat
= &sdata
->vif
.bss_conf
.chandef
;
369 compat
= cfg80211_chandef_compatible(
370 &sdata
->vif
.bss_conf
.chandef
, compat
);
376 if (WARN_ON_ONCE(!compat
))
379 ieee80211_change_chanctx(local
, ctx
, compat
);
382 static void ieee80211_recalc_radar_chanctx(struct ieee80211_local
*local
,
383 struct ieee80211_chanctx
*chanctx
)
387 lockdep_assert_held(&local
->chanctx_mtx
);
388 /* for setting local->radar_detect_enabled */
389 lockdep_assert_held(&local
->mtx
);
391 radar_enabled
= ieee80211_is_radar_required(local
);
393 if (radar_enabled
== chanctx
->conf
.radar_enabled
)
396 chanctx
->conf
.radar_enabled
= radar_enabled
;
397 local
->radar_detect_enabled
= chanctx
->conf
.radar_enabled
;
399 if (!local
->use_chanctx
) {
400 local
->hw
.conf
.radar_enabled
= chanctx
->conf
.radar_enabled
;
401 ieee80211_hw_config(local
, IEEE80211_CONF_CHANGE_CHANNEL
);
404 drv_change_chanctx(local
, chanctx
, IEEE80211_CHANCTX_CHANGE_RADAR
);
407 static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data
*sdata
,
408 struct ieee80211_chanctx
*new_ctx
)
410 struct ieee80211_local
*local
= sdata
->local
;
411 struct ieee80211_chanctx_conf
*conf
;
412 struct ieee80211_chanctx
*curr_ctx
= NULL
;
415 conf
= rcu_dereference_protected(sdata
->vif
.chanctx_conf
,
416 lockdep_is_held(&local
->chanctx_mtx
));
419 curr_ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
421 curr_ctx
->refcount
--;
422 drv_unassign_vif_chanctx(local
, sdata
, curr_ctx
);
424 list_del(&sdata
->assigned_chanctx_list
);
428 ret
= drv_assign_vif_chanctx(local
, sdata
, new_ctx
);
433 conf
= &new_ctx
->conf
;
434 list_add(&sdata
->assigned_chanctx_list
,
435 &new_ctx
->assigned_vifs
);
439 rcu_assign_pointer(sdata
->vif
.chanctx_conf
, conf
);
441 sdata
->vif
.bss_conf
.idle
= !conf
;
443 if (curr_ctx
&& curr_ctx
->refcount
> 0) {
444 ieee80211_recalc_chanctx_chantype(local
, curr_ctx
);
445 ieee80211_recalc_smps_chanctx(local
, curr_ctx
);
446 ieee80211_recalc_radar_chanctx(local
, curr_ctx
);
447 ieee80211_recalc_chanctx_min_def(local
, curr_ctx
);
450 if (new_ctx
&& new_ctx
->refcount
> 0) {
451 ieee80211_recalc_txpower(sdata
);
452 ieee80211_recalc_chanctx_min_def(local
, new_ctx
);
455 if (sdata
->vif
.type
!= NL80211_IFTYPE_P2P_DEVICE
&&
456 sdata
->vif
.type
!= NL80211_IFTYPE_MONITOR
)
457 ieee80211_bss_info_change_notify(sdata
,
463 static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data
*sdata
)
465 struct ieee80211_local
*local
= sdata
->local
;
466 struct ieee80211_chanctx_conf
*conf
;
467 struct ieee80211_chanctx
*ctx
;
469 lockdep_assert_held(&local
->chanctx_mtx
);
471 conf
= rcu_dereference_protected(sdata
->vif
.chanctx_conf
,
472 lockdep_is_held(&local
->chanctx_mtx
));
476 ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
478 if (sdata
->reserved_chanctx
)
479 ieee80211_vif_unreserve_chanctx(sdata
);
481 ieee80211_assign_vif_chanctx(sdata
, NULL
);
482 if (ctx
->refcount
== 0)
483 ieee80211_free_chanctx(local
, ctx
);
486 void ieee80211_recalc_smps_chanctx(struct ieee80211_local
*local
,
487 struct ieee80211_chanctx
*chanctx
)
489 struct ieee80211_sub_if_data
*sdata
;
490 u8 rx_chains_static
, rx_chains_dynamic
;
492 lockdep_assert_held(&local
->chanctx_mtx
);
494 rx_chains_static
= 1;
495 rx_chains_dynamic
= 1;
498 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
499 u8 needed_static
, needed_dynamic
;
501 if (!ieee80211_sdata_running(sdata
))
504 if (rcu_access_pointer(sdata
->vif
.chanctx_conf
) !=
508 switch (sdata
->vif
.type
) {
509 case NL80211_IFTYPE_P2P_DEVICE
:
511 case NL80211_IFTYPE_STATION
:
512 if (!sdata
->u
.mgd
.associated
)
515 case NL80211_IFTYPE_AP_VLAN
:
517 case NL80211_IFTYPE_AP
:
518 case NL80211_IFTYPE_ADHOC
:
519 case NL80211_IFTYPE_WDS
:
520 case NL80211_IFTYPE_MESH_POINT
:
526 switch (sdata
->smps_mode
) {
528 WARN_ONCE(1, "Invalid SMPS mode %d\n",
531 case IEEE80211_SMPS_OFF
:
532 needed_static
= sdata
->needed_rx_chains
;
533 needed_dynamic
= sdata
->needed_rx_chains
;
535 case IEEE80211_SMPS_DYNAMIC
:
537 needed_dynamic
= sdata
->needed_rx_chains
;
539 case IEEE80211_SMPS_STATIC
:
545 rx_chains_static
= max(rx_chains_static
, needed_static
);
546 rx_chains_dynamic
= max(rx_chains_dynamic
, needed_dynamic
);
550 if (!local
->use_chanctx
) {
551 if (rx_chains_static
> 1)
552 local
->smps_mode
= IEEE80211_SMPS_OFF
;
553 else if (rx_chains_dynamic
> 1)
554 local
->smps_mode
= IEEE80211_SMPS_DYNAMIC
;
556 local
->smps_mode
= IEEE80211_SMPS_STATIC
;
557 ieee80211_hw_config(local
, 0);
560 if (rx_chains_static
== chanctx
->conf
.rx_chains_static
&&
561 rx_chains_dynamic
== chanctx
->conf
.rx_chains_dynamic
)
564 chanctx
->conf
.rx_chains_static
= rx_chains_static
;
565 chanctx
->conf
.rx_chains_dynamic
= rx_chains_dynamic
;
566 drv_change_chanctx(local
, chanctx
, IEEE80211_CHANCTX_CHANGE_RX_CHAINS
);
569 int ieee80211_vif_use_channel(struct ieee80211_sub_if_data
*sdata
,
570 const struct cfg80211_chan_def
*chandef
,
571 enum ieee80211_chanctx_mode mode
)
573 struct ieee80211_local
*local
= sdata
->local
;
574 struct ieee80211_chanctx
*ctx
;
575 u8 radar_detect_width
= 0;
578 lockdep_assert_held(&local
->mtx
);
580 WARN_ON(sdata
->dev
&& netif_carrier_ok(sdata
->dev
));
582 mutex_lock(&local
->chanctx_mtx
);
584 ret
= cfg80211_chandef_dfs_required(local
->hw
.wiphy
,
590 radar_detect_width
= BIT(chandef
->width
);
592 sdata
->radar_required
= ret
;
594 ret
= ieee80211_check_combinations(sdata
, chandef
, mode
,
599 __ieee80211_vif_release_channel(sdata
);
601 ctx
= ieee80211_find_chanctx(local
, chandef
, mode
);
603 ctx
= ieee80211_new_chanctx(local
, chandef
, mode
);
609 sdata
->vif
.bss_conf
.chandef
= *chandef
;
611 ret
= ieee80211_assign_vif_chanctx(sdata
, ctx
);
613 /* if assign fails refcount stays the same */
614 if (ctx
->refcount
== 0)
615 ieee80211_free_chanctx(local
, ctx
);
619 ieee80211_recalc_smps_chanctx(local
, ctx
);
620 ieee80211_recalc_radar_chanctx(local
, ctx
);
622 mutex_unlock(&local
->chanctx_mtx
);
626 static int __ieee80211_vif_change_channel(struct ieee80211_sub_if_data
*sdata
,
627 struct ieee80211_chanctx
*ctx
,
630 struct ieee80211_local
*local
= sdata
->local
;
631 const struct cfg80211_chan_def
*chandef
= &sdata
->csa_chandef
;
632 u32 chanctx_changed
= 0;
634 if (!cfg80211_chandef_usable(sdata
->local
->hw
.wiphy
, chandef
,
635 IEEE80211_CHAN_DISABLED
))
638 if (ctx
->refcount
!= 1)
641 if (sdata
->vif
.bss_conf
.chandef
.width
!= chandef
->width
) {
642 chanctx_changed
= IEEE80211_CHANCTX_CHANGE_WIDTH
;
643 *changed
|= BSS_CHANGED_BANDWIDTH
;
646 sdata
->vif
.bss_conf
.chandef
= *chandef
;
647 ctx
->conf
.def
= *chandef
;
649 chanctx_changed
|= IEEE80211_CHANCTX_CHANGE_CHANNEL
;
650 drv_change_chanctx(local
, ctx
, chanctx_changed
);
652 ieee80211_recalc_chanctx_chantype(local
, ctx
);
653 ieee80211_recalc_smps_chanctx(local
, ctx
);
654 ieee80211_recalc_radar_chanctx(local
, ctx
);
655 ieee80211_recalc_chanctx_min_def(local
, ctx
);
660 int ieee80211_vif_change_channel(struct ieee80211_sub_if_data
*sdata
,
663 struct ieee80211_local
*local
= sdata
->local
;
664 struct ieee80211_chanctx_conf
*conf
;
665 struct ieee80211_chanctx
*ctx
;
668 lockdep_assert_held(&local
->mtx
);
670 /* should never be called if not performing a channel switch. */
671 if (WARN_ON(!sdata
->vif
.csa_active
))
674 mutex_lock(&local
->chanctx_mtx
);
675 conf
= rcu_dereference_protected(sdata
->vif
.chanctx_conf
,
676 lockdep_is_held(&local
->chanctx_mtx
));
682 ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
684 ret
= __ieee80211_vif_change_channel(sdata
, ctx
, changed
);
686 mutex_unlock(&local
->chanctx_mtx
);
691 __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data
*sdata
,
694 struct ieee80211_local
*local
= sdata
->local
;
695 struct ieee80211_sub_if_data
*vlan
;
696 struct ieee80211_chanctx_conf
*conf
;
698 if (WARN_ON(sdata
->vif
.type
!= NL80211_IFTYPE_AP
))
701 lockdep_assert_held(&local
->mtx
);
703 /* Check that conf exists, even when clearing this function
704 * must be called with the AP's channel context still there
705 * as it would otherwise cause VLANs to have an invalid
706 * channel context pointer for a while, possibly pointing
707 * to a channel context that has already been freed.
709 conf
= rcu_dereference_protected(sdata
->vif
.chanctx_conf
,
710 lockdep_is_held(&local
->chanctx_mtx
));
716 list_for_each_entry(vlan
, &sdata
->u
.ap
.vlans
, u
.vlan
.list
)
717 rcu_assign_pointer(vlan
->vif
.chanctx_conf
, conf
);
720 void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data
*sdata
,
723 struct ieee80211_local
*local
= sdata
->local
;
725 mutex_lock(&local
->chanctx_mtx
);
727 __ieee80211_vif_copy_chanctx_to_vlans(sdata
, clear
);
729 mutex_unlock(&local
->chanctx_mtx
);
732 int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data
*sdata
)
734 lockdep_assert_held(&sdata
->local
->chanctx_mtx
);
736 if (WARN_ON(!sdata
->reserved_chanctx
))
739 if (--sdata
->reserved_chanctx
->refcount
== 0)
740 ieee80211_free_chanctx(sdata
->local
, sdata
->reserved_chanctx
);
742 sdata
->reserved_chanctx
= NULL
;
747 int ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data
*sdata
,
748 const struct cfg80211_chan_def
*chandef
,
749 enum ieee80211_chanctx_mode mode
,
752 struct ieee80211_local
*local
= sdata
->local
;
753 struct ieee80211_chanctx_conf
*conf
;
754 struct ieee80211_chanctx
*new_ctx
, *curr_ctx
;
757 mutex_lock(&local
->chanctx_mtx
);
759 conf
= rcu_dereference_protected(sdata
->vif
.chanctx_conf
,
760 lockdep_is_held(&local
->chanctx_mtx
));
766 curr_ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
768 /* try to find another context with the chandef we want */
769 new_ctx
= ieee80211_find_chanctx(local
, chandef
, mode
);
771 if (curr_ctx
->refcount
== 1 &&
772 (local
->hw
.flags
& IEEE80211_HW_CHANGE_RUNNING_CHANCTX
)) {
773 /* if we're the only users of the chanctx and
774 * the driver supports changing a running
775 * context, reserve our current context
778 } else if (ieee80211_can_create_new_chanctx(local
)) {
779 /* create a new context and reserve it */
780 new_ctx
= ieee80211_new_chanctx(local
, chandef
, mode
);
781 if (IS_ERR(new_ctx
)) {
782 ret
= PTR_ERR(new_ctx
);
792 sdata
->reserved_chanctx
= new_ctx
;
793 sdata
->reserved_chandef
= *chandef
;
794 sdata
->reserved_radar_required
= radar_required
;
796 mutex_unlock(&local
->chanctx_mtx
);
800 int ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data
*sdata
,
803 struct ieee80211_local
*local
= sdata
->local
;
804 struct ieee80211_chanctx
*ctx
;
805 struct ieee80211_chanctx
*old_ctx
;
806 struct ieee80211_chanctx_conf
*conf
;
808 u32 tmp_changed
= *changed
;
810 /* TODO: need to recheck if the chandef is usable etc.? */
812 lockdep_assert_held(&local
->mtx
);
814 mutex_lock(&local
->chanctx_mtx
);
816 ctx
= sdata
->reserved_chanctx
;
822 conf
= rcu_dereference_protected(sdata
->vif
.chanctx_conf
,
823 lockdep_is_held(&local
->chanctx_mtx
));
829 old_ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
831 if (sdata
->vif
.bss_conf
.chandef
.width
!= sdata
->reserved_chandef
.width
)
832 tmp_changed
|= BSS_CHANGED_BANDWIDTH
;
834 sdata
->vif
.bss_conf
.chandef
= sdata
->reserved_chandef
;
836 /* unref our reservation */
838 sdata
->reserved_chanctx
= NULL
;
839 sdata
->radar_required
= sdata
->reserved_radar_required
;
841 if (old_ctx
== ctx
) {
842 /* This is our own context, just change it */
843 ret
= __ieee80211_vif_change_channel(sdata
, old_ctx
,
848 ret
= ieee80211_assign_vif_chanctx(sdata
, ctx
);
849 if (old_ctx
->refcount
== 0)
850 ieee80211_free_chanctx(local
, old_ctx
);
852 /* if assign fails refcount stays the same */
853 if (ctx
->refcount
== 0)
854 ieee80211_free_chanctx(local
, ctx
);
858 if (sdata
->vif
.type
== NL80211_IFTYPE_AP
)
859 __ieee80211_vif_copy_chanctx_to_vlans(sdata
, false);
862 *changed
= tmp_changed
;
864 ieee80211_recalc_chanctx_chantype(local
, ctx
);
865 ieee80211_recalc_smps_chanctx(local
, ctx
);
866 ieee80211_recalc_radar_chanctx(local
, ctx
);
867 ieee80211_recalc_chanctx_min_def(local
, ctx
);
869 mutex_unlock(&local
->chanctx_mtx
);
873 int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data
*sdata
,
874 const struct cfg80211_chan_def
*chandef
,
877 struct ieee80211_local
*local
= sdata
->local
;
878 struct ieee80211_chanctx_conf
*conf
;
879 struct ieee80211_chanctx
*ctx
;
882 if (!cfg80211_chandef_usable(sdata
->local
->hw
.wiphy
, chandef
,
883 IEEE80211_CHAN_DISABLED
))
886 mutex_lock(&local
->chanctx_mtx
);
887 if (cfg80211_chandef_identical(chandef
, &sdata
->vif
.bss_conf
.chandef
)) {
892 if (chandef
->width
== NL80211_CHAN_WIDTH_20_NOHT
||
893 sdata
->vif
.bss_conf
.chandef
.width
== NL80211_CHAN_WIDTH_20_NOHT
) {
898 conf
= rcu_dereference_protected(sdata
->vif
.chanctx_conf
,
899 lockdep_is_held(&local
->chanctx_mtx
));
905 ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
906 if (!cfg80211_chandef_compatible(&conf
->def
, chandef
)) {
911 sdata
->vif
.bss_conf
.chandef
= *chandef
;
913 ieee80211_recalc_chanctx_chantype(local
, ctx
);
915 *changed
|= BSS_CHANGED_BANDWIDTH
;
918 mutex_unlock(&local
->chanctx_mtx
);
922 void ieee80211_vif_release_channel(struct ieee80211_sub_if_data
*sdata
)
924 WARN_ON(sdata
->dev
&& netif_carrier_ok(sdata
->dev
));
926 lockdep_assert_held(&sdata
->local
->mtx
);
928 mutex_lock(&sdata
->local
->chanctx_mtx
);
929 __ieee80211_vif_release_channel(sdata
);
930 mutex_unlock(&sdata
->local
->chanctx_mtx
);
933 void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data
*sdata
)
935 struct ieee80211_local
*local
= sdata
->local
;
936 struct ieee80211_sub_if_data
*ap
;
937 struct ieee80211_chanctx_conf
*conf
;
939 if (WARN_ON(sdata
->vif
.type
!= NL80211_IFTYPE_AP_VLAN
|| !sdata
->bss
))
942 ap
= container_of(sdata
->bss
, struct ieee80211_sub_if_data
, u
.ap
);
944 mutex_lock(&local
->chanctx_mtx
);
946 conf
= rcu_dereference_protected(ap
->vif
.chanctx_conf
,
947 lockdep_is_held(&local
->chanctx_mtx
));
948 rcu_assign_pointer(sdata
->vif
.chanctx_conf
, conf
);
949 mutex_unlock(&local
->chanctx_mtx
);
952 void ieee80211_iter_chan_contexts_atomic(
953 struct ieee80211_hw
*hw
,
954 void (*iter
)(struct ieee80211_hw
*hw
,
955 struct ieee80211_chanctx_conf
*chanctx_conf
,
959 struct ieee80211_local
*local
= hw_to_local(hw
);
960 struct ieee80211_chanctx
*ctx
;
963 list_for_each_entry_rcu(ctx
, &local
->chanctx_list
, list
)
964 if (ctx
->driver_present
)
965 iter(hw
, &ctx
->conf
, iter_data
);
968 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic
);