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 void ieee80211_change_chanctx(struct ieee80211_local
*local
,
13 struct ieee80211_chanctx
*ctx
,
14 const struct cfg80211_chan_def
*chandef
)
16 if (cfg80211_chandef_identical(&ctx
->conf
.def
, chandef
))
19 WARN_ON(!cfg80211_chandef_compatible(&ctx
->conf
.def
, chandef
));
21 ctx
->conf
.def
= *chandef
;
22 drv_change_chanctx(local
, ctx
, IEEE80211_CHANCTX_CHANGE_WIDTH
);
24 if (!local
->use_chanctx
) {
25 local
->_oper_chandef
= *chandef
;
26 ieee80211_hw_config(local
, 0);
30 static struct ieee80211_chanctx
*
31 ieee80211_find_chanctx(struct ieee80211_local
*local
,
32 const struct cfg80211_chan_def
*chandef
,
33 enum ieee80211_chanctx_mode mode
)
35 struct ieee80211_chanctx
*ctx
;
37 lockdep_assert_held(&local
->chanctx_mtx
);
39 if (mode
== IEEE80211_CHANCTX_EXCLUSIVE
)
42 list_for_each_entry(ctx
, &local
->chanctx_list
, list
) {
43 const struct cfg80211_chan_def
*compat
;
45 if (ctx
->mode
== IEEE80211_CHANCTX_EXCLUSIVE
)
48 compat
= cfg80211_chandef_compatible(&ctx
->conf
.def
, chandef
);
52 ieee80211_change_chanctx(local
, ctx
, compat
);
60 static bool ieee80211_is_radar_required(struct ieee80211_local
*local
)
62 struct ieee80211_sub_if_data
*sdata
;
65 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
66 if (sdata
->radar_required
) {
76 static struct ieee80211_chanctx
*
77 ieee80211_new_chanctx(struct ieee80211_local
*local
,
78 const struct cfg80211_chan_def
*chandef
,
79 enum ieee80211_chanctx_mode mode
)
81 struct ieee80211_chanctx
*ctx
;
85 lockdep_assert_held(&local
->chanctx_mtx
);
87 ctx
= kzalloc(sizeof(*ctx
) + local
->hw
.chanctx_data_size
, GFP_KERNEL
);
89 return ERR_PTR(-ENOMEM
);
91 ctx
->conf
.def
= *chandef
;
92 ctx
->conf
.rx_chains_static
= 1;
93 ctx
->conf
.rx_chains_dynamic
= 1;
95 ctx
->conf
.radar_enabled
= ieee80211_is_radar_required(local
);
96 if (!local
->use_chanctx
)
97 local
->hw
.conf
.radar_enabled
= ctx
->conf
.radar_enabled
;
99 /* acquire mutex to prevent idle from changing */
100 mutex_lock(&local
->mtx
);
101 /* turn idle off *before* setting channel -- some drivers need that */
102 changed
= ieee80211_idle_off(local
);
104 ieee80211_hw_config(local
, changed
);
106 if (!local
->use_chanctx
) {
107 local
->_oper_chandef
= *chandef
;
108 ieee80211_hw_config(local
, 0);
110 err
= drv_add_chanctx(local
, ctx
);
115 ieee80211_recalc_idle(local
);
120 /* and keep the mutex held until the new chanctx is on the list */
121 list_add_rcu(&ctx
->list
, &local
->chanctx_list
);
124 mutex_unlock(&local
->mtx
);
129 static void ieee80211_free_chanctx(struct ieee80211_local
*local
,
130 struct ieee80211_chanctx
*ctx
)
132 bool check_single_channel
= false;
133 lockdep_assert_held(&local
->chanctx_mtx
);
135 WARN_ON_ONCE(ctx
->refcount
!= 0);
137 if (!local
->use_chanctx
) {
138 struct cfg80211_chan_def
*chandef
= &local
->_oper_chandef
;
139 chandef
->width
= NL80211_CHAN_WIDTH_20_NOHT
;
140 chandef
->center_freq1
= chandef
->chan
->center_freq
;
141 chandef
->center_freq2
= 0;
143 /* NOTE: Disabling radar is only valid here for
144 * single channel context. To be sure, check it ...
146 if (local
->hw
.conf
.radar_enabled
)
147 check_single_channel
= true;
148 local
->hw
.conf
.radar_enabled
= false;
150 ieee80211_hw_config(local
, 0);
152 drv_remove_chanctx(local
, ctx
);
155 list_del_rcu(&ctx
->list
);
156 kfree_rcu(ctx
, rcu_head
);
158 /* throw a warning if this wasn't the only channel context. */
159 WARN_ON(check_single_channel
&& !list_empty(&local
->chanctx_list
));
161 mutex_lock(&local
->mtx
);
162 ieee80211_recalc_idle(local
);
163 mutex_unlock(&local
->mtx
);
166 static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data
*sdata
,
167 struct ieee80211_chanctx
*ctx
)
169 struct ieee80211_local
*local
= sdata
->local
;
172 lockdep_assert_held(&local
->chanctx_mtx
);
174 ret
= drv_assign_vif_chanctx(local
, sdata
, ctx
);
178 rcu_assign_pointer(sdata
->vif
.chanctx_conf
, &ctx
->conf
);
181 ieee80211_recalc_txpower(sdata
);
182 sdata
->vif
.bss_conf
.idle
= false;
184 if (sdata
->vif
.type
!= NL80211_IFTYPE_P2P_DEVICE
&&
185 sdata
->vif
.type
!= NL80211_IFTYPE_MONITOR
)
186 ieee80211_bss_info_change_notify(sdata
, BSS_CHANGED_IDLE
);
191 static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local
*local
,
192 struct ieee80211_chanctx
*ctx
)
194 struct ieee80211_chanctx_conf
*conf
= &ctx
->conf
;
195 struct ieee80211_sub_if_data
*sdata
;
196 const struct cfg80211_chan_def
*compat
= NULL
;
198 lockdep_assert_held(&local
->chanctx_mtx
);
201 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
203 if (!ieee80211_sdata_running(sdata
))
205 if (rcu_access_pointer(sdata
->vif
.chanctx_conf
) != conf
)
209 compat
= &sdata
->vif
.bss_conf
.chandef
;
211 compat
= cfg80211_chandef_compatible(
212 &sdata
->vif
.bss_conf
.chandef
, compat
);
218 if (WARN_ON_ONCE(!compat
))
221 ieee80211_change_chanctx(local
, ctx
, compat
);
224 static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data
*sdata
,
225 struct ieee80211_chanctx
*ctx
)
227 struct ieee80211_local
*local
= sdata
->local
;
229 lockdep_assert_held(&local
->chanctx_mtx
);
232 rcu_assign_pointer(sdata
->vif
.chanctx_conf
, NULL
);
234 sdata
->vif
.bss_conf
.idle
= true;
236 if (sdata
->vif
.type
!= NL80211_IFTYPE_P2P_DEVICE
&&
237 sdata
->vif
.type
!= NL80211_IFTYPE_MONITOR
)
238 ieee80211_bss_info_change_notify(sdata
, BSS_CHANGED_IDLE
);
240 drv_unassign_vif_chanctx(local
, sdata
, ctx
);
242 if (ctx
->refcount
> 0) {
243 ieee80211_recalc_chanctx_chantype(sdata
->local
, ctx
);
244 ieee80211_recalc_smps_chanctx(local
, ctx
);
245 ieee80211_recalc_radar_chanctx(local
, ctx
);
249 static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data
*sdata
)
251 struct ieee80211_local
*local
= sdata
->local
;
252 struct ieee80211_chanctx_conf
*conf
;
253 struct ieee80211_chanctx
*ctx
;
255 lockdep_assert_held(&local
->chanctx_mtx
);
257 conf
= rcu_dereference_protected(sdata
->vif
.chanctx_conf
,
258 lockdep_is_held(&local
->chanctx_mtx
));
262 ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
264 ieee80211_unassign_vif_chanctx(sdata
, ctx
);
265 if (ctx
->refcount
== 0)
266 ieee80211_free_chanctx(local
, ctx
);
269 void ieee80211_recalc_radar_chanctx(struct ieee80211_local
*local
,
270 struct ieee80211_chanctx
*chanctx
)
274 lockdep_assert_held(&local
->chanctx_mtx
);
276 radar_enabled
= ieee80211_is_radar_required(local
);
278 if (radar_enabled
== chanctx
->conf
.radar_enabled
)
281 chanctx
->conf
.radar_enabled
= radar_enabled
;
282 local
->radar_detect_enabled
= chanctx
->conf
.radar_enabled
;
284 if (!local
->use_chanctx
) {
285 local
->hw
.conf
.radar_enabled
= chanctx
->conf
.radar_enabled
;
286 ieee80211_hw_config(local
, IEEE80211_CONF_CHANGE_CHANNEL
);
289 drv_change_chanctx(local
, chanctx
, IEEE80211_CHANCTX_CHANGE_RADAR
);
292 void ieee80211_recalc_smps_chanctx(struct ieee80211_local
*local
,
293 struct ieee80211_chanctx
*chanctx
)
295 struct ieee80211_sub_if_data
*sdata
;
296 u8 rx_chains_static
, rx_chains_dynamic
;
298 lockdep_assert_held(&local
->chanctx_mtx
);
300 rx_chains_static
= 1;
301 rx_chains_dynamic
= 1;
304 list_for_each_entry_rcu(sdata
, &local
->interfaces
, list
) {
305 u8 needed_static
, needed_dynamic
;
307 if (!ieee80211_sdata_running(sdata
))
310 if (rcu_access_pointer(sdata
->vif
.chanctx_conf
) !=
314 switch (sdata
->vif
.type
) {
315 case NL80211_IFTYPE_P2P_DEVICE
:
317 case NL80211_IFTYPE_STATION
:
318 if (!sdata
->u
.mgd
.associated
)
321 case NL80211_IFTYPE_AP_VLAN
:
323 case NL80211_IFTYPE_AP
:
324 case NL80211_IFTYPE_ADHOC
:
325 case NL80211_IFTYPE_WDS
:
326 case NL80211_IFTYPE_MESH_POINT
:
332 switch (sdata
->smps_mode
) {
334 WARN_ONCE(1, "Invalid SMPS mode %d\n",
337 case IEEE80211_SMPS_OFF
:
338 needed_static
= sdata
->needed_rx_chains
;
339 needed_dynamic
= sdata
->needed_rx_chains
;
341 case IEEE80211_SMPS_DYNAMIC
:
343 needed_dynamic
= sdata
->needed_rx_chains
;
345 case IEEE80211_SMPS_STATIC
:
351 rx_chains_static
= max(rx_chains_static
, needed_static
);
352 rx_chains_dynamic
= max(rx_chains_dynamic
, needed_dynamic
);
356 if (!local
->use_chanctx
) {
357 if (rx_chains_static
> 1)
358 local
->smps_mode
= IEEE80211_SMPS_OFF
;
359 else if (rx_chains_dynamic
> 1)
360 local
->smps_mode
= IEEE80211_SMPS_DYNAMIC
;
362 local
->smps_mode
= IEEE80211_SMPS_STATIC
;
363 ieee80211_hw_config(local
, 0);
366 if (rx_chains_static
== chanctx
->conf
.rx_chains_static
&&
367 rx_chains_dynamic
== chanctx
->conf
.rx_chains_dynamic
)
370 chanctx
->conf
.rx_chains_static
= rx_chains_static
;
371 chanctx
->conf
.rx_chains_dynamic
= rx_chains_dynamic
;
372 drv_change_chanctx(local
, chanctx
, IEEE80211_CHANCTX_CHANGE_RX_CHAINS
);
375 int ieee80211_vif_use_channel(struct ieee80211_sub_if_data
*sdata
,
376 const struct cfg80211_chan_def
*chandef
,
377 enum ieee80211_chanctx_mode mode
)
379 struct ieee80211_local
*local
= sdata
->local
;
380 struct ieee80211_chanctx
*ctx
;
383 WARN_ON(sdata
->dev
&& netif_carrier_ok(sdata
->dev
));
385 mutex_lock(&local
->chanctx_mtx
);
386 __ieee80211_vif_release_channel(sdata
);
388 ctx
= ieee80211_find_chanctx(local
, chandef
, mode
);
390 ctx
= ieee80211_new_chanctx(local
, chandef
, mode
);
396 sdata
->vif
.bss_conf
.chandef
= *chandef
;
398 ret
= ieee80211_assign_vif_chanctx(sdata
, ctx
);
400 /* if assign fails refcount stays the same */
401 if (ctx
->refcount
== 0)
402 ieee80211_free_chanctx(local
, ctx
);
406 ieee80211_recalc_smps_chanctx(local
, ctx
);
407 ieee80211_recalc_radar_chanctx(local
, ctx
);
409 mutex_unlock(&local
->chanctx_mtx
);
413 int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data
*sdata
,
414 const struct cfg80211_chan_def
*chandef
,
417 struct ieee80211_local
*local
= sdata
->local
;
418 struct ieee80211_chanctx_conf
*conf
;
419 struct ieee80211_chanctx
*ctx
;
422 if (!cfg80211_chandef_usable(sdata
->local
->hw
.wiphy
, chandef
,
423 IEEE80211_CHAN_DISABLED
))
426 mutex_lock(&local
->chanctx_mtx
);
427 if (cfg80211_chandef_identical(chandef
, &sdata
->vif
.bss_conf
.chandef
)) {
432 if (chandef
->width
== NL80211_CHAN_WIDTH_20_NOHT
||
433 sdata
->vif
.bss_conf
.chandef
.width
== NL80211_CHAN_WIDTH_20_NOHT
) {
438 conf
= rcu_dereference_protected(sdata
->vif
.chanctx_conf
,
439 lockdep_is_held(&local
->chanctx_mtx
));
445 ctx
= container_of(conf
, struct ieee80211_chanctx
, conf
);
446 if (!cfg80211_chandef_compatible(&conf
->def
, chandef
)) {
451 sdata
->vif
.bss_conf
.chandef
= *chandef
;
453 ieee80211_recalc_chanctx_chantype(local
, ctx
);
455 *changed
|= BSS_CHANGED_BANDWIDTH
;
458 mutex_unlock(&local
->chanctx_mtx
);
462 void ieee80211_vif_release_channel(struct ieee80211_sub_if_data
*sdata
)
464 WARN_ON(sdata
->dev
&& netif_carrier_ok(sdata
->dev
));
466 mutex_lock(&sdata
->local
->chanctx_mtx
);
467 __ieee80211_vif_release_channel(sdata
);
468 mutex_unlock(&sdata
->local
->chanctx_mtx
);
471 void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data
*sdata
)
473 struct ieee80211_local
*local
= sdata
->local
;
474 struct ieee80211_sub_if_data
*ap
;
475 struct ieee80211_chanctx_conf
*conf
;
477 if (WARN_ON(sdata
->vif
.type
!= NL80211_IFTYPE_AP_VLAN
|| !sdata
->bss
))
480 ap
= container_of(sdata
->bss
, struct ieee80211_sub_if_data
, u
.ap
);
482 mutex_lock(&local
->chanctx_mtx
);
484 conf
= rcu_dereference_protected(ap
->vif
.chanctx_conf
,
485 lockdep_is_held(&local
->chanctx_mtx
));
486 rcu_assign_pointer(sdata
->vif
.chanctx_conf
, conf
);
487 mutex_unlock(&local
->chanctx_mtx
);
490 void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data
*sdata
,
493 struct ieee80211_local
*local
= sdata
->local
;
494 struct ieee80211_sub_if_data
*vlan
;
495 struct ieee80211_chanctx_conf
*conf
;
499 if (WARN_ON(sdata
->vif
.type
!= NL80211_IFTYPE_AP
))
502 mutex_lock(&local
->chanctx_mtx
);
505 * Check that conf exists, even when clearing this function
506 * must be called with the AP's channel context still there
507 * as it would otherwise cause VLANs to have an invalid
508 * channel context pointer for a while, possibly pointing
509 * to a channel context that has already been freed.
511 conf
= rcu_dereference_protected(sdata
->vif
.chanctx_conf
,
512 lockdep_is_held(&local
->chanctx_mtx
));
518 list_for_each_entry(vlan
, &sdata
->u
.ap
.vlans
, u
.vlan
.list
)
519 rcu_assign_pointer(vlan
->vif
.chanctx_conf
, conf
);
521 mutex_unlock(&local
->chanctx_mtx
);
524 void ieee80211_iter_chan_contexts_atomic(
525 struct ieee80211_hw
*hw
,
526 void (*iter
)(struct ieee80211_hw
*hw
,
527 struct ieee80211_chanctx_conf
*chanctx_conf
,
531 struct ieee80211_local
*local
= hw_to_local(hw
);
532 struct ieee80211_chanctx
*ctx
;
535 list_for_each_entry_rcu(ctx
, &local
->chanctx_list
, list
)
536 if (ctx
->driver_present
)
537 iter(hw
, &ctx
->conf
, iter_data
);
540 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic
);