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 enum nl80211_chan_width
ieee80211_get_sta_bw(struct ieee80211_sta
*sta
)
14 switch (sta
->bandwidth
) {
15 case IEEE80211_STA_RX_BW_20
:
16 if (sta
->ht_cap
.ht_supported
)
17 return NL80211_CHAN_WIDTH_20
;
19 return NL80211_CHAN_WIDTH_20_NOHT
;
20 case IEEE80211_STA_RX_BW_40
:
21 return NL80211_CHAN_WIDTH_40
;
22 case IEEE80211_STA_RX_BW_80
:
23 return NL80211_CHAN_WIDTH_80
;
24 case IEEE80211_STA_RX_BW_160
:
26 * This applied for both 160 and 80+80. since we use
27 * the returned value to consider degradation of
28 * ctx->conf.min_def, we have to make sure to take
29 * the bigger one (NL80211_CHAN_WIDTH_160).
30 * Otherwise we might try degrading even when not
31 * needed, as the max required sta_bw returned (80+80)
32 * might be smaller than the configured bw (160).
34 return NL80211_CHAN_WIDTH_160
;
37 return NL80211_CHAN_WIDTH_20
;
41 static enum nl80211_chan_width
42 ieee80211_get_max_required_bw(struct ieee80211_sub_if_data
*sdata
)
44 enum nl80211_chan_width max_bw
= NL80211_CHAN_WIDTH_20_NOHT
;
48 list_for_each_entry_rcu(sta
, &sdata
->local
->sta_list
, list
) {
49 if (sdata
!= sta
->sdata
&&
50 !(sta
->sdata
->bss
&& sta
->sdata
->bss
== sdata
->bss
))
56 max_bw
= max(max_bw
, ieee80211_get_sta_bw(&sta
->sta
));
63 static enum nl80211_chan_width
64 ieee80211_get_chanctx_max_required_bw(struct ieee80211_local
*local
,
65 struct ieee80211_chanctx_conf
*conf
)
67 struct ieee80211_sub_if_data
*sdata
;
68 enum nl80211_chan_width max_bw
= NL80211_CHAN_WIDTH_20_NOHT
;
71 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
72 struct ieee80211_vif
*vif
= &sdata
->vif
;
73 enum nl80211_chan_width width
= NL80211_CHAN_WIDTH_20_NOHT
;
75 if (!ieee80211_sdata_running(sdata
))
78 if (rcu_access_pointer(sdata
->vif
.chanctx_conf
) != conf
)
82 case NL80211_IFTYPE_AP
:
83 case NL80211_IFTYPE_AP_VLAN
:
84 width
= ieee80211_get_max_required_bw(sdata
);
86 case NL80211_IFTYPE_P2P_DEVICE
:
88 case NL80211_IFTYPE_STATION
:
89 case NL80211_IFTYPE_ADHOC
:
90 case NL80211_IFTYPE_WDS
:
91 case NL80211_IFTYPE_MESH_POINT
:
92 width
= vif
->bss_conf
.chandef
.width
;
94 case NL80211_IFTYPE_UNSPECIFIED
:
95 case NUM_NL80211_IFTYPES
:
96 case NL80211_IFTYPE_MONITOR
:
97 case NL80211_IFTYPE_P2P_CLIENT
:
98 case NL80211_IFTYPE_P2P_GO
:
101 max_bw
= max(max_bw
, width
);
104 /* use the configured bandwidth in case of monitor interface */
105 sdata
= rcu_dereference(local
->monitor_sdata
);
106 if (sdata
&& rcu_access_pointer(sdata
->vif
.chanctx_conf
) == conf
)
107 max_bw
= max(max_bw
, conf
->def
.width
);
115 * recalc the min required chan width of the channel context, which is
116 * the max of min required widths of all the interfaces bound to this
119 void ieee80211_recalc_chanctx_min_def(struct ieee80211_local
*local
,
120 struct ieee80211_chanctx
*ctx
)
122 enum nl80211_chan_width max_bw
;
123 struct cfg80211_chan_def min_def
;
125 lockdep_assert_held(&local
->chanctx_mtx
);
127 /* don't optimize 5MHz, 10MHz, and radar_enabled confs */
128 if (ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_5
||
129 ctx
->conf
.def
.width
== NL80211_CHAN_WIDTH_10
||
130 ctx
->conf
.radar_enabled
) {
131 ctx
->conf
.min_def
= ctx
->conf
.def
;
135 max_bw
= ieee80211_get_chanctx_max_required_bw(local
, &ctx
->conf
);
137 /* downgrade chandef up to max_bw */
138 min_def
= ctx
->conf
.def
;
139 while (min_def
.width
> max_bw
)
140 ieee80211_chandef_downgrade(&min_def
);
142 if (cfg80211_chandef_identical(&ctx
->conf
.min_def
, &min_def
))
145 ctx
->conf
.min_def
= min_def
;
146 if (!ctx
->driver_present
)
149 drv_change_chanctx(local
, ctx
, IEEE80211_CHANCTX_CHANGE_MIN_WIDTH
);
152 static void ieee80211_change_chanctx(struct ieee80211_local
*local
,
153 struct ieee80211_chanctx
*ctx
,
154 const struct cfg80211_chan_def
*chandef
)
156 if (cfg80211_chandef_identical(&ctx
->conf
.def
, chandef
))
159 WARN_ON(!cfg80211_chandef_compatible(&ctx
->conf
.def
, chandef
));
161 ctx
->conf
.def
= *chandef
;
162 drv_change_chanctx(local
, ctx
, IEEE80211_CHANCTX_CHANGE_WIDTH
);
163 ieee80211_recalc_chanctx_min_def(local
, ctx
);
165 if (!local
->use_chanctx
) {
166 local
->_oper_chandef
= *chandef
;
167 ieee80211_hw_config(local
, 0);
171 static struct ieee80211_chanctx
*
172 ieee80211_find_chanctx(struct ieee80211_local
*local
,
173 const struct cfg80211_chan_def
*chandef
,
174 enum ieee80211_chanctx_mode mode
)
176 struct ieee80211_chanctx
*ctx
;
178 lockdep_assert_held(&local
->chanctx_mtx
);
180 if (mode
== IEEE80211_CHANCTX_EXCLUSIVE
)
183 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
184 const struct cfg80211_chan_def
*compat
;
186 if (ctx
->mode
== IEEE80211_CHANCTX_EXCLUSIVE
)
189 compat
= cfg80211_chandef_compatible(&ctx
->conf
.def
, chandef
);
193 ieee80211_change_chanctx(local
, ctx
, compat
);
201 static bool ieee80211_is_radar_required(struct ieee80211_local
*local
)
203 struct ieee80211_sub_if_data
*sdata
;
206 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
207 if (sdata
->radar_required
) {
217 static struct ieee80211_chanctx
*
218 ieee80211_new_chanctx(struct ieee80211_local
*local
,
219 const struct cfg80211_chan_def
*chandef
,
220 enum ieee80211_chanctx_mode mode
)
222 struct ieee80211_chanctx
*ctx
;
226 lockdep_assert_held(&local
->chanctx_mtx
);
228 ctx
= kzalloc(sizeof(*ctx
) + local
->hw
.chanctx_data_size
, GFP_KERNEL
);
230 return ERR_PTR(-ENOMEM
);
232 ctx
->conf
.def
= *chandef
;
233 ctx
->conf
.rx_chains_static
= 1;
234 ctx
->conf
.rx_chains_dynamic
= 1;
236 ctx
->conf
.radar_enabled
= ieee80211_is_radar_required(local
);
237 ieee80211_recalc_chanctx_min_def(local
, ctx
);
238 if (!local
->use_chanctx
)
239 local
->hw
.conf
.radar_enabled
= ctx
->conf
.radar_enabled
;
241 /* we hold the mutex to prevent idle from changing */
242 lockdep_assert_held(&local
->mtx
);
243 /* turn idle off *before* setting channel -- some drivers need that */
244 changed
= ieee80211_idle_off(local
);
246 ieee80211_hw_config(local
, changed
);
248 if (!local
->use_chanctx
) {
249 local
->_oper_chandef
= *chandef
;
250 ieee80211_hw_config(local
, 0);
252 err
= drv_add_chanctx(local
, ctx
);
255 ieee80211_recalc_idle(local
);
260 /* and keep the mutex held until the new chanctx is on the list */
261 list_add_rcu(&ctx
->list
, &local
->chanctx_list
);
266 static void ieee80211_free_chanctx(struct ieee80211_local
*local
,
267 struct ieee80211_chanctx
*ctx
)
269 bool check_single_channel
= false;
270 lockdep_assert_held(&local
->chanctx_mtx
);
272 WARN_ON_ONCE(ctx
->refcount
!= 0);
274 if (!local
->use_chanctx
) {
275 struct cfg80211_chan_def
*chandef
= &local
->_oper_chandef
;
276 chandef
->width
= NL80211_CHAN_WIDTH_20_NOHT
;
277 chandef
->center_freq1
= chandef
->chan
->center_freq
;
278 chandef
->center_freq2
= 0;
280 /* NOTE: Disabling radar is only valid here for
281 * single channel context. To be sure, check it ...
283 if (local
->hw
.conf
.radar_enabled
)
284 check_single_channel
= true;
285 local
->hw
.conf
.radar_enabled
= false;
287 ieee80211_hw_config(local
, 0);
289 drv_remove_chanctx(local
, ctx
);
292 list_del_rcu(&ctx
->list
);
293 kfree_rcu(ctx
, rcu_head
);
295 /* throw a warning if this wasn't the only channel context. */
296 WARN_ON(check_single_channel
&& !list_empty(&local
->chanctx_list
));
298 ieee80211_recalc_idle(local
);
301 static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data
*sdata
,
302 struct ieee80211_chanctx
*ctx
)
304 struct ieee80211_local
*local
= sdata
->local
;
307 lockdep_assert_held(&local
->chanctx_mtx
);
309 ret
= drv_assign_vif_chanctx(local
, sdata
, ctx
);
313 rcu_assign_pointer(sdata
->vif
.chanctx_conf
, &ctx
->conf
);
316 ieee80211_recalc_txpower(sdata
);
317 ieee80211_recalc_chanctx_min_def(local
, ctx
);
318 sdata
->vif
.bss_conf
.idle
= false;
320 if (sdata
->vif
.type
!= NL80211_IFTYPE_P2P_DEVICE
&&
321 sdata
->vif
.type
!= NL80211_IFTYPE_MONITOR
)
322 ieee80211_bss_info_change_notify(sdata
, BSS_CHANGED_IDLE
);
327 static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local
*local
,
328 struct ieee80211_chanctx
*ctx
)
330 struct ieee80211_chanctx_conf
*conf
= &ctx
->conf
;
331 struct ieee80211_sub_if_data
*sdata
;
332 const struct cfg80211_chan_def
*compat
= NULL
;
334 lockdep_assert_held(&local
->chanctx_mtx
);
337 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
339 if (!ieee80211_sdata_running(sdata
))
341 if (rcu_access_pointer(sdata
->vif
.chanctx_conf
) != conf
)
345 compat
= &sdata
->vif
.bss_conf
.chandef
;
347 compat
= cfg80211_chandef_compatible(
348 &sdata
->vif
.bss_conf
.chandef
, compat
);
354 if (WARN_ON_ONCE(!compat
))
357 ieee80211_change_chanctx(local
, ctx
, compat
);
360 static void ieee80211_recalc_radar_chanctx(struct ieee80211_local
*local
,
361 struct ieee80211_chanctx
*chanctx
)
365 lockdep_assert_held(&local
->chanctx_mtx
);
366 /* for setting local->radar_detect_enabled */
367 lockdep_assert_held(&local
->mtx
);
369 radar_enabled
= ieee80211_is_radar_required(local
);
371 if (radar_enabled
== chanctx
->conf
.radar_enabled
)
374 chanctx
->conf
.radar_enabled
= radar_enabled
;
375 local
->radar_detect_enabled
= chanctx
->conf
.radar_enabled
;
377 if (!local
->use_chanctx
) {
378 local
->hw
.conf
.radar_enabled
= chanctx
->conf
.radar_enabled
;
379 ieee80211_hw_config(local
, IEEE80211_CONF_CHANGE_CHANNEL
);
382 drv_change_chanctx(local
, chanctx
, IEEE80211_CHANCTX_CHANGE_RADAR
);
385 static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data
*sdata
,
386 struct ieee80211_chanctx
*ctx
)
388 struct ieee80211_local
*local
= sdata
->local
;
390 lockdep_assert_held(&local
->chanctx_mtx
);
393 rcu_assign_pointer(sdata
->vif
.chanctx_conf
, NULL
);
395 sdata
->vif
.bss_conf
.idle
= true;
397 if (sdata
->vif
.type
!= NL80211_IFTYPE_P2P_DEVICE
&&
398 sdata
->vif
.type
!= NL80211_IFTYPE_MONITOR
)
399 ieee80211_bss_info_change_notify(sdata
, BSS_CHANGED_IDLE
);
401 drv_unassign_vif_chanctx(local
, sdata
, ctx
);
403 if (ctx
->refcount
> 0) {
404 ieee80211_recalc_chanctx_chantype(sdata
->local
, ctx
);
405 ieee80211_recalc_smps_chanctx(local
, ctx
);
406 ieee80211_recalc_radar_chanctx(local
, ctx
);
407 ieee80211_recalc_chanctx_min_def(local
, ctx
);
411 static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data
*sdata
)
413 struct ieee80211_local
*local
= sdata
->local
;
414 struct ieee80211_chanctx_conf
*conf
;
415 struct ieee80211_chanctx
*ctx
;
417 lockdep_assert_held(&local
->chanctx_mtx
);
419 conf
= rcu_dereference_protected(sdata
->vif
.chanctx_conf
,
420 lockdep_is_held(&local
->chanctx_mtx
));
424 ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
426 ieee80211_unassign_vif_chanctx(sdata
, ctx
);
427 if (ctx
->refcount
== 0)
428 ieee80211_free_chanctx(local
, ctx
);
431 void ieee80211_recalc_smps_chanctx(struct ieee80211_local
*local
,
432 struct ieee80211_chanctx
*chanctx
)
434 struct ieee80211_sub_if_data
*sdata
;
435 u8 rx_chains_static
, rx_chains_dynamic
;
437 lockdep_assert_held(&local
->chanctx_mtx
);
439 rx_chains_static
= 1;
440 rx_chains_dynamic
= 1;
443 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
444 u8 needed_static
, needed_dynamic
;
446 if (!ieee80211_sdata_running(sdata
))
449 if (rcu_access_pointer(sdata
->vif
.chanctx_conf
) !=
453 switch (sdata
->vif
.type
) {
454 case NL80211_IFTYPE_P2P_DEVICE
:
456 case NL80211_IFTYPE_STATION
:
457 if (!sdata
->u
.mgd
.associated
)
460 case NL80211_IFTYPE_AP_VLAN
:
462 case NL80211_IFTYPE_AP
:
463 case NL80211_IFTYPE_ADHOC
:
464 case NL80211_IFTYPE_WDS
:
465 case NL80211_IFTYPE_MESH_POINT
:
471 switch (sdata
->smps_mode
) {
473 WARN_ONCE(1, "Invalid SMPS mode %d\n",
476 case IEEE80211_SMPS_OFF
:
477 needed_static
= sdata
->needed_rx_chains
;
478 needed_dynamic
= sdata
->needed_rx_chains
;
480 case IEEE80211_SMPS_DYNAMIC
:
482 needed_dynamic
= sdata
->needed_rx_chains
;
484 case IEEE80211_SMPS_STATIC
:
490 rx_chains_static
= max(rx_chains_static
, needed_static
);
491 rx_chains_dynamic
= max(rx_chains_dynamic
, needed_dynamic
);
495 if (!local
->use_chanctx
) {
496 if (rx_chains_static
> 1)
497 local
->smps_mode
= IEEE80211_SMPS_OFF
;
498 else if (rx_chains_dynamic
> 1)
499 local
->smps_mode
= IEEE80211_SMPS_DYNAMIC
;
501 local
->smps_mode
= IEEE80211_SMPS_STATIC
;
502 ieee80211_hw_config(local
, 0);
505 if (rx_chains_static
== chanctx
->conf
.rx_chains_static
&&
506 rx_chains_dynamic
== chanctx
->conf
.rx_chains_dynamic
)
509 chanctx
->conf
.rx_chains_static
= rx_chains_static
;
510 chanctx
->conf
.rx_chains_dynamic
= rx_chains_dynamic
;
511 drv_change_chanctx(local
, chanctx
, IEEE80211_CHANCTX_CHANGE_RX_CHAINS
);
514 int ieee80211_vif_use_channel(struct ieee80211_sub_if_data
*sdata
,
515 const struct cfg80211_chan_def
*chandef
,
516 enum ieee80211_chanctx_mode mode
)
518 struct ieee80211_local
*local
= sdata
->local
;
519 struct ieee80211_chanctx
*ctx
;
522 lockdep_assert_held(&local
->mtx
);
524 WARN_ON(sdata
->dev
&& netif_carrier_ok(sdata
->dev
));
526 mutex_lock(&local
->chanctx_mtx
);
527 __ieee80211_vif_release_channel(sdata
);
529 ctx
= ieee80211_find_chanctx(local
, chandef
, mode
);
531 ctx
= ieee80211_new_chanctx(local
, chandef
, mode
);
537 sdata
->vif
.bss_conf
.chandef
= *chandef
;
539 ret
= ieee80211_assign_vif_chanctx(sdata
, ctx
);
541 /* if assign fails refcount stays the same */
542 if (ctx
->refcount
== 0)
543 ieee80211_free_chanctx(local
, ctx
);
547 ieee80211_recalc_smps_chanctx(local
, ctx
);
548 ieee80211_recalc_radar_chanctx(local
, ctx
);
550 mutex_unlock(&local
->chanctx_mtx
);
554 int ieee80211_vif_change_channel(struct ieee80211_sub_if_data
*sdata
,
557 struct ieee80211_local
*local
= sdata
->local
;
558 struct ieee80211_chanctx_conf
*conf
;
559 struct ieee80211_chanctx
*ctx
;
560 const struct cfg80211_chan_def
*chandef
= &sdata
->csa_chandef
;
562 u32 chanctx_changed
= 0;
564 lockdep_assert_held(&local
->mtx
);
566 /* should never be called if not performing a channel switch. */
567 if (WARN_ON(!sdata
->vif
.csa_active
))
570 if (!cfg80211_chandef_usable(sdata
->local
->hw
.wiphy
, chandef
,
571 IEEE80211_CHAN_DISABLED
))
574 mutex_lock(&local
->chanctx_mtx
);
575 conf
= rcu_dereference_protected(sdata
->vif
.chanctx_conf
,
576 lockdep_is_held(&local
->chanctx_mtx
));
582 ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
583 if (ctx
->refcount
!= 1) {
588 if (sdata
->vif
.bss_conf
.chandef
.width
!= chandef
->width
) {
589 chanctx_changed
= IEEE80211_CHANCTX_CHANGE_WIDTH
;
590 *changed
|= BSS_CHANGED_BANDWIDTH
;
593 sdata
->vif
.bss_conf
.chandef
= *chandef
;
594 ctx
->conf
.def
= *chandef
;
596 chanctx_changed
|= IEEE80211_CHANCTX_CHANGE_CHANNEL
;
597 drv_change_chanctx(local
, ctx
, chanctx_changed
);
599 ieee80211_recalc_chanctx_chantype(local
, ctx
);
600 ieee80211_recalc_smps_chanctx(local
, ctx
);
601 ieee80211_recalc_radar_chanctx(local
, ctx
);
602 ieee80211_recalc_chanctx_min_def(local
, ctx
);
606 mutex_unlock(&local
->chanctx_mtx
);
610 int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data
*sdata
,
611 const struct cfg80211_chan_def
*chandef
,
614 struct ieee80211_local
*local
= sdata
->local
;
615 struct ieee80211_chanctx_conf
*conf
;
616 struct ieee80211_chanctx
*ctx
;
619 if (!cfg80211_chandef_usable(sdata
->local
->hw
.wiphy
, chandef
,
620 IEEE80211_CHAN_DISABLED
))
623 mutex_lock(&local
->chanctx_mtx
);
624 if (cfg80211_chandef_identical(chandef
, &sdata
->vif
.bss_conf
.chandef
)) {
629 if (chandef
->width
== NL80211_CHAN_WIDTH_20_NOHT
||
630 sdata
->vif
.bss_conf
.chandef
.width
== NL80211_CHAN_WIDTH_20_NOHT
) {
635 conf
= rcu_dereference_protected(sdata
->vif
.chanctx_conf
,
636 lockdep_is_held(&local
->chanctx_mtx
));
642 ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
643 if (!cfg80211_chandef_compatible(&conf
->def
, chandef
)) {
648 sdata
->vif
.bss_conf
.chandef
= *chandef
;
650 ieee80211_recalc_chanctx_chantype(local
, ctx
);
652 *changed
|= BSS_CHANGED_BANDWIDTH
;
655 mutex_unlock(&local
->chanctx_mtx
);
659 void ieee80211_vif_release_channel(struct ieee80211_sub_if_data
*sdata
)
661 WARN_ON(sdata
->dev
&& netif_carrier_ok(sdata
->dev
));
663 lockdep_assert_held(&sdata
->local
->mtx
);
665 mutex_lock(&sdata
->local
->chanctx_mtx
);
666 __ieee80211_vif_release_channel(sdata
);
667 mutex_unlock(&sdata
->local
->chanctx_mtx
);
670 void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data
*sdata
)
672 struct ieee80211_local
*local
= sdata
->local
;
673 struct ieee80211_sub_if_data
*ap
;
674 struct ieee80211_chanctx_conf
*conf
;
676 if (WARN_ON(sdata
->vif
.type
!= NL80211_IFTYPE_AP_VLAN
|| !sdata
->bss
))
679 ap
= container_of(sdata
->bss
, struct ieee80211_sub_if_data
, u
.ap
);
681 mutex_lock(&local
->chanctx_mtx
);
683 conf
= rcu_dereference_protected(ap
->vif
.chanctx_conf
,
684 lockdep_is_held(&local
->chanctx_mtx
));
685 rcu_assign_pointer(sdata
->vif
.chanctx_conf
, conf
);
686 mutex_unlock(&local
->chanctx_mtx
);
689 void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data
*sdata
,
692 struct ieee80211_local
*local
= sdata
->local
;
693 struct ieee80211_sub_if_data
*vlan
;
694 struct ieee80211_chanctx_conf
*conf
;
698 if (WARN_ON(sdata
->vif
.type
!= NL80211_IFTYPE_AP
))
701 mutex_lock(&local
->chanctx_mtx
);
704 * Check that conf exists, even when clearing this function
705 * must be called with the AP's channel context still there
706 * as it would otherwise cause VLANs to have an invalid
707 * channel context pointer for a while, possibly pointing
708 * to a channel context that has already been freed.
710 conf
= rcu_dereference_protected(sdata
->vif
.chanctx_conf
,
711 lockdep_is_held(&local
->chanctx_mtx
));
717 list_for_each_entry(vlan
, &sdata
->u
.ap
.vlans
, u
.vlan
.list
)
718 rcu_assign_pointer(vlan
->vif
.chanctx_conf
, conf
);
720 mutex_unlock(&local
->chanctx_mtx
);
723 void ieee80211_iter_chan_contexts_atomic(
724 struct ieee80211_hw
*hw
,
725 void (*iter
)(struct ieee80211_hw
*hw
,
726 struct ieee80211_chanctx_conf
*chanctx_conf
,
730 struct ieee80211_local
*local
= hw_to_local(hw
);
731 struct ieee80211_chanctx
*ctx
;
734 list_for_each_entry_rcu(ctx
, &local
->chanctx_list
, list
)
735 if (ctx
->driver_present
)
736 iter(hw
, &ctx
->conf
, iter_data
);
739 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic
);