2 * cfg80211 MLME SAP interface
4 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/etherdevice.h>
10 #include <linux/netdevice.h>
11 #include <linux/nl80211.h>
12 #include <linux/slab.h>
13 #include <linux/wireless.h>
14 #include <net/cfg80211.h>
15 #include <net/iw_handler.h>
21 void cfg80211_rx_assoc_resp(struct net_device
*dev
, struct cfg80211_bss
*bss
,
22 const u8
*buf
, size_t len
)
24 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
25 struct wiphy
*wiphy
= wdev
->wiphy
;
26 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
27 struct ieee80211_mgmt
*mgmt
= (struct ieee80211_mgmt
*)buf
;
28 u8
*ie
= mgmt
->u
.assoc_resp
.variable
;
29 int ieoffs
= offsetof(struct ieee80211_mgmt
, u
.assoc_resp
.variable
);
30 u16 status_code
= le16_to_cpu(mgmt
->u
.assoc_resp
.status_code
);
32 trace_cfg80211_send_rx_assoc(dev
, bss
);
35 * This is a bit of a hack, we don't notify userspace of
36 * a (re-)association reply if we tried to send a reassoc
37 * and got a reject -- we only try again with an assoc
38 * frame instead of reassoc.
40 if (cfg80211_sme_rx_assoc_resp(wdev
, status_code
)) {
41 cfg80211_unhold_bss(bss_from_pub(bss
));
42 cfg80211_put_bss(wiphy
, bss
);
46 nl80211_send_rx_assoc(rdev
, dev
, buf
, len
, GFP_KERNEL
);
47 /* update current_bss etc., consumes the bss reference */
48 __cfg80211_connect_result(dev
, mgmt
->bssid
, NULL
, 0, ie
, len
- ieoffs
,
50 status_code
== WLAN_STATUS_SUCCESS
, bss
);
52 EXPORT_SYMBOL(cfg80211_rx_assoc_resp
);
54 static void cfg80211_process_auth(struct wireless_dev
*wdev
,
55 const u8
*buf
, size_t len
)
57 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
59 nl80211_send_rx_auth(rdev
, wdev
->netdev
, buf
, len
, GFP_KERNEL
);
60 cfg80211_sme_rx_auth(wdev
, buf
, len
);
63 static void cfg80211_process_deauth(struct wireless_dev
*wdev
,
64 const u8
*buf
, size_t len
)
66 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
67 struct ieee80211_mgmt
*mgmt
= (struct ieee80211_mgmt
*)buf
;
68 const u8
*bssid
= mgmt
->bssid
;
69 u16 reason_code
= le16_to_cpu(mgmt
->u
.deauth
.reason_code
);
70 bool from_ap
= !ether_addr_equal(mgmt
->sa
, wdev
->netdev
->dev_addr
);
72 nl80211_send_deauth(rdev
, wdev
->netdev
, buf
, len
, GFP_KERNEL
);
74 if (!wdev
->current_bss
||
75 !ether_addr_equal(wdev
->current_bss
->pub
.bssid
, bssid
))
78 __cfg80211_disconnected(wdev
->netdev
, NULL
, 0, reason_code
, from_ap
);
79 cfg80211_sme_deauth(wdev
);
82 static void cfg80211_process_disassoc(struct wireless_dev
*wdev
,
83 const u8
*buf
, size_t len
)
85 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wdev
->wiphy
);
86 struct ieee80211_mgmt
*mgmt
= (struct ieee80211_mgmt
*)buf
;
87 const u8
*bssid
= mgmt
->bssid
;
88 u16 reason_code
= le16_to_cpu(mgmt
->u
.disassoc
.reason_code
);
89 bool from_ap
= !ether_addr_equal(mgmt
->sa
, wdev
->netdev
->dev_addr
);
91 nl80211_send_disassoc(rdev
, wdev
->netdev
, buf
, len
, GFP_KERNEL
);
93 if (WARN_ON(!wdev
->current_bss
||
94 !ether_addr_equal(wdev
->current_bss
->pub
.bssid
, bssid
)))
97 __cfg80211_disconnected(wdev
->netdev
, NULL
, 0, reason_code
, from_ap
);
98 cfg80211_sme_disassoc(wdev
);
101 void cfg80211_rx_mlme_mgmt(struct net_device
*dev
, const u8
*buf
, size_t len
)
103 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
104 struct ieee80211_mgmt
*mgmt
= (void *)buf
;
106 ASSERT_WDEV_LOCK(wdev
);
108 trace_cfg80211_rx_mlme_mgmt(dev
, buf
, len
);
110 if (WARN_ON(len
< 2))
113 if (ieee80211_is_auth(mgmt
->frame_control
))
114 cfg80211_process_auth(wdev
, buf
, len
);
115 else if (ieee80211_is_deauth(mgmt
->frame_control
))
116 cfg80211_process_deauth(wdev
, buf
, len
);
117 else if (ieee80211_is_disassoc(mgmt
->frame_control
))
118 cfg80211_process_disassoc(wdev
, buf
, len
);
120 EXPORT_SYMBOL(cfg80211_rx_mlme_mgmt
);
122 void cfg80211_auth_timeout(struct net_device
*dev
, const u8
*addr
)
124 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
125 struct wiphy
*wiphy
= wdev
->wiphy
;
126 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
128 trace_cfg80211_send_auth_timeout(dev
, addr
);
130 nl80211_send_auth_timeout(rdev
, dev
, addr
, GFP_KERNEL
);
131 cfg80211_sme_auth_timeout(wdev
);
133 EXPORT_SYMBOL(cfg80211_auth_timeout
);
135 void cfg80211_assoc_timeout(struct net_device
*dev
, struct cfg80211_bss
*bss
)
137 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
138 struct wiphy
*wiphy
= wdev
->wiphy
;
139 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
141 trace_cfg80211_send_assoc_timeout(dev
, bss
->bssid
);
143 nl80211_send_assoc_timeout(rdev
, dev
, bss
->bssid
, GFP_KERNEL
);
144 cfg80211_sme_assoc_timeout(wdev
);
146 cfg80211_unhold_bss(bss_from_pub(bss
));
147 cfg80211_put_bss(wiphy
, bss
);
149 EXPORT_SYMBOL(cfg80211_assoc_timeout
);
151 void cfg80211_tx_mlme_mgmt(struct net_device
*dev
, const u8
*buf
, size_t len
)
153 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
154 struct ieee80211_mgmt
*mgmt
= (void *)buf
;
156 ASSERT_WDEV_LOCK(wdev
);
158 trace_cfg80211_tx_mlme_mgmt(dev
, buf
, len
);
160 if (WARN_ON(len
< 2))
163 if (ieee80211_is_deauth(mgmt
->frame_control
))
164 cfg80211_process_deauth(wdev
, buf
, len
);
166 cfg80211_process_disassoc(wdev
, buf
, len
);
168 EXPORT_SYMBOL(cfg80211_tx_mlme_mgmt
);
170 void cfg80211_michael_mic_failure(struct net_device
*dev
, const u8
*addr
,
171 enum nl80211_key_type key_type
, int key_id
,
172 const u8
*tsc
, gfp_t gfp
)
174 struct wiphy
*wiphy
= dev
->ieee80211_ptr
->wiphy
;
175 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
176 #ifdef CONFIG_CFG80211_WEXT
177 union iwreq_data wrqu
;
178 char *buf
= kmalloc(128, gfp
);
181 sprintf(buf
, "MLME-MICHAELMICFAILURE.indication("
182 "keyid=%d %scast addr=%pM)", key_id
,
183 key_type
== NL80211_KEYTYPE_GROUP
? "broad" : "uni",
185 memset(&wrqu
, 0, sizeof(wrqu
));
186 wrqu
.data
.length
= strlen(buf
);
187 wireless_send_event(dev
, IWEVCUSTOM
, &wrqu
, buf
);
192 trace_cfg80211_michael_mic_failure(dev
, addr
, key_type
, key_id
, tsc
);
193 nl80211_michael_mic_failure(rdev
, dev
, addr
, key_type
, key_id
, tsc
, gfp
);
195 EXPORT_SYMBOL(cfg80211_michael_mic_failure
);
197 /* some MLME handling for userspace SME */
198 int cfg80211_mlme_auth(struct cfg80211_registered_device
*rdev
,
199 struct net_device
*dev
,
200 struct ieee80211_channel
*chan
,
201 enum nl80211_auth_type auth_type
,
203 const u8
*ssid
, int ssid_len
,
204 const u8
*ie
, int ie_len
,
205 const u8
*key
, int key_len
, int key_idx
,
206 const u8
*sae_data
, int sae_data_len
)
208 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
209 struct cfg80211_auth_request req
= {
212 .sae_data
= sae_data
,
213 .sae_data_len
= sae_data_len
,
214 .auth_type
= auth_type
,
221 ASSERT_WDEV_LOCK(wdev
);
223 if (auth_type
== NL80211_AUTHTYPE_SHARED_KEY
)
224 if (!key
|| !key_len
|| key_idx
< 0 || key_idx
> 4)
227 if (wdev
->current_bss
&&
228 ether_addr_equal(bssid
, wdev
->current_bss
->pub
.bssid
))
231 req
.bss
= cfg80211_get_bss(&rdev
->wiphy
, chan
, bssid
, ssid
, ssid_len
,
232 WLAN_CAPABILITY_ESS
, WLAN_CAPABILITY_ESS
);
236 err
= cfg80211_can_use_chan(rdev
, wdev
, req
.bss
->channel
,
241 err
= rdev_auth(rdev
, dev
, &req
);
244 cfg80211_put_bss(&rdev
->wiphy
, req
.bss
);
248 /* Do a logical ht_capa &= ht_capa_mask. */
249 void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap
*ht_capa
,
250 const struct ieee80211_ht_cap
*ht_capa_mask
)
255 memset(ht_capa
, 0, sizeof(*ht_capa
));
260 p2
= (u8
*)(ht_capa_mask
);
261 for (i
= 0; i
<sizeof(*ht_capa
); i
++)
265 /* Do a logical ht_capa &= ht_capa_mask. */
266 void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap
*vht_capa
,
267 const struct ieee80211_vht_cap
*vht_capa_mask
)
271 if (!vht_capa_mask
) {
272 memset(vht_capa
, 0, sizeof(*vht_capa
));
276 p1
= (u8
*)(vht_capa
);
277 p2
= (u8
*)(vht_capa_mask
);
278 for (i
= 0; i
< sizeof(*vht_capa
); i
++)
282 int cfg80211_mlme_assoc(struct cfg80211_registered_device
*rdev
,
283 struct net_device
*dev
,
284 struct ieee80211_channel
*chan
,
286 const u8
*ssid
, int ssid_len
,
287 struct cfg80211_assoc_request
*req
)
289 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
292 ASSERT_WDEV_LOCK(wdev
);
294 if (wdev
->current_bss
&&
295 (!req
->prev_bssid
|| !ether_addr_equal(wdev
->current_bss
->pub
.bssid
,
299 cfg80211_oper_and_ht_capa(&req
->ht_capa_mask
,
300 rdev
->wiphy
.ht_capa_mod_mask
);
301 cfg80211_oper_and_vht_capa(&req
->vht_capa_mask
,
302 rdev
->wiphy
.vht_capa_mod_mask
);
304 req
->bss
= cfg80211_get_bss(&rdev
->wiphy
, chan
, bssid
, ssid
, ssid_len
,
305 WLAN_CAPABILITY_ESS
, WLAN_CAPABILITY_ESS
);
309 err
= cfg80211_can_use_chan(rdev
, wdev
, chan
, CHAN_MODE_SHARED
);
313 err
= rdev_assoc(rdev
, dev
, req
);
315 cfg80211_hold_bss(bss_from_pub(req
->bss
));
319 cfg80211_put_bss(&rdev
->wiphy
, req
->bss
);
324 int cfg80211_mlme_deauth(struct cfg80211_registered_device
*rdev
,
325 struct net_device
*dev
, const u8
*bssid
,
326 const u8
*ie
, int ie_len
, u16 reason
,
327 bool local_state_change
)
329 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
330 struct cfg80211_deauth_request req
= {
332 .reason_code
= reason
,
335 .local_state_change
= local_state_change
,
338 ASSERT_WDEV_LOCK(wdev
);
340 if (local_state_change
&&
341 (!wdev
->current_bss
||
342 !ether_addr_equal(wdev
->current_bss
->pub
.bssid
, bssid
)))
345 return rdev_deauth(rdev
, dev
, &req
);
348 int cfg80211_mlme_disassoc(struct cfg80211_registered_device
*rdev
,
349 struct net_device
*dev
, const u8
*bssid
,
350 const u8
*ie
, int ie_len
, u16 reason
,
351 bool local_state_change
)
353 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
354 struct cfg80211_disassoc_request req
= {
355 .reason_code
= reason
,
356 .local_state_change
= local_state_change
,
362 ASSERT_WDEV_LOCK(wdev
);
364 if (!wdev
->current_bss
)
367 if (ether_addr_equal(wdev
->current_bss
->pub
.bssid
, bssid
))
368 req
.bss
= &wdev
->current_bss
->pub
;
372 err
= rdev_disassoc(rdev
, dev
, &req
);
376 /* driver should have reported the disassoc */
377 WARN_ON(wdev
->current_bss
);
381 void cfg80211_mlme_down(struct cfg80211_registered_device
*rdev
,
382 struct net_device
*dev
)
384 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
387 ASSERT_WDEV_LOCK(wdev
);
389 if (!rdev
->ops
->deauth
)
392 if (!wdev
->current_bss
)
395 memcpy(bssid
, wdev
->current_bss
->pub
.bssid
, ETH_ALEN
);
396 cfg80211_mlme_deauth(rdev
, dev
, bssid
, NULL
, 0,
397 WLAN_REASON_DEAUTH_LEAVING
, false);
400 struct cfg80211_mgmt_registration
{
401 struct list_head list
;
412 int cfg80211_mlme_register_mgmt(struct wireless_dev
*wdev
, u32 snd_portid
,
413 u16 frame_type
, const u8
*match_data
,
416 struct wiphy
*wiphy
= wdev
->wiphy
;
417 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
418 struct cfg80211_mgmt_registration
*reg
, *nreg
;
422 if (!wdev
->wiphy
->mgmt_stypes
)
425 if ((frame_type
& IEEE80211_FCTL_FTYPE
) != IEEE80211_FTYPE_MGMT
)
428 if (frame_type
& ~(IEEE80211_FCTL_FTYPE
| IEEE80211_FCTL_STYPE
))
431 mgmt_type
= (frame_type
& IEEE80211_FCTL_STYPE
) >> 4;
432 if (!(wdev
->wiphy
->mgmt_stypes
[wdev
->iftype
].rx
& BIT(mgmt_type
)))
435 nreg
= kzalloc(sizeof(*reg
) + match_len
, GFP_KERNEL
);
439 spin_lock_bh(&wdev
->mgmt_registrations_lock
);
441 list_for_each_entry(reg
, &wdev
->mgmt_registrations
, list
) {
442 int mlen
= min(match_len
, reg
->match_len
);
444 if (frame_type
!= le16_to_cpu(reg
->frame_type
))
447 if (memcmp(reg
->match
, match_data
, mlen
) == 0) {
458 memcpy(nreg
->match
, match_data
, match_len
);
459 nreg
->match_len
= match_len
;
460 nreg
->nlportid
= snd_portid
;
461 nreg
->frame_type
= cpu_to_le16(frame_type
);
462 list_add(&nreg
->list
, &wdev
->mgmt_registrations
);
464 if (rdev
->ops
->mgmt_frame_register
)
465 rdev_mgmt_frame_register(rdev
, wdev
, frame_type
, true);
468 spin_unlock_bh(&wdev
->mgmt_registrations_lock
);
473 void cfg80211_mlme_unregister_socket(struct wireless_dev
*wdev
, u32 nlportid
)
475 struct wiphy
*wiphy
= wdev
->wiphy
;
476 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
477 struct cfg80211_mgmt_registration
*reg
, *tmp
;
479 spin_lock_bh(&wdev
->mgmt_registrations_lock
);
481 list_for_each_entry_safe(reg
, tmp
, &wdev
->mgmt_registrations
, list
) {
482 if (reg
->nlportid
!= nlportid
)
485 if (rdev
->ops
->mgmt_frame_register
) {
486 u16 frame_type
= le16_to_cpu(reg
->frame_type
);
488 rdev_mgmt_frame_register(rdev
, wdev
,
492 list_del(®
->list
);
496 spin_unlock_bh(&wdev
->mgmt_registrations_lock
);
498 if (nlportid
&& rdev
->crit_proto_nlportid
== nlportid
) {
499 rdev
->crit_proto_nlportid
= 0;
500 rdev_crit_proto_stop(rdev
, wdev
);
503 if (nlportid
== wdev
->ap_unexpected_nlportid
)
504 wdev
->ap_unexpected_nlportid
= 0;
507 void cfg80211_mlme_purge_registrations(struct wireless_dev
*wdev
)
509 struct cfg80211_mgmt_registration
*reg
, *tmp
;
511 spin_lock_bh(&wdev
->mgmt_registrations_lock
);
513 list_for_each_entry_safe(reg
, tmp
, &wdev
->mgmt_registrations
, list
) {
514 list_del(®
->list
);
518 spin_unlock_bh(&wdev
->mgmt_registrations_lock
);
521 int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device
*rdev
,
522 struct wireless_dev
*wdev
,
523 struct cfg80211_mgmt_tx_params
*params
, u64
*cookie
)
525 const struct ieee80211_mgmt
*mgmt
;
528 if (!wdev
->wiphy
->mgmt_stypes
)
531 if (!rdev
->ops
->mgmt_tx
)
534 if (params
->len
< 24 + 1)
537 mgmt
= (const struct ieee80211_mgmt
*)params
->buf
;
539 if (!ieee80211_is_mgmt(mgmt
->frame_control
))
542 stype
= le16_to_cpu(mgmt
->frame_control
) & IEEE80211_FCTL_STYPE
;
543 if (!(wdev
->wiphy
->mgmt_stypes
[wdev
->iftype
].tx
& BIT(stype
>> 4)))
546 if (ieee80211_is_action(mgmt
->frame_control
) &&
547 mgmt
->u
.action
.category
!= WLAN_CATEGORY_PUBLIC
) {
552 switch (wdev
->iftype
) {
553 case NL80211_IFTYPE_ADHOC
:
554 case NL80211_IFTYPE_STATION
:
555 case NL80211_IFTYPE_P2P_CLIENT
:
556 if (!wdev
->current_bss
) {
561 if (!ether_addr_equal(wdev
->current_bss
->pub
.bssid
,
568 * check for IBSS DA must be done by driver as
569 * cfg80211 doesn't track the stations
571 if (wdev
->iftype
== NL80211_IFTYPE_ADHOC
)
574 /* for station, check that DA is the AP */
575 if (!ether_addr_equal(wdev
->current_bss
->pub
.bssid
,
581 case NL80211_IFTYPE_AP
:
582 case NL80211_IFTYPE_P2P_GO
:
583 case NL80211_IFTYPE_AP_VLAN
:
584 if (!ether_addr_equal(mgmt
->bssid
, wdev_address(wdev
)))
587 case NL80211_IFTYPE_MESH_POINT
:
588 if (!ether_addr_equal(mgmt
->sa
, mgmt
->bssid
)) {
593 * check for mesh DA must be done by driver as
594 * cfg80211 doesn't track the stations
597 case NL80211_IFTYPE_P2P_DEVICE
:
599 * fall through, P2P device only supports
600 * public action frames
612 if (!ether_addr_equal(mgmt
->sa
, wdev_address(wdev
)))
615 /* Transmit the Action frame as requested by user space */
616 return rdev_mgmt_tx(rdev
, wdev
, params
, cookie
);
619 bool cfg80211_rx_mgmt(struct wireless_dev
*wdev
, int freq
, int sig_mbm
,
620 const u8
*buf
, size_t len
, u32 flags
, gfp_t gfp
)
622 struct wiphy
*wiphy
= wdev
->wiphy
;
623 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
624 struct cfg80211_mgmt_registration
*reg
;
625 const struct ieee80211_txrx_stypes
*stypes
=
626 &wiphy
->mgmt_stypes
[wdev
->iftype
];
627 struct ieee80211_mgmt
*mgmt
= (void *)buf
;
631 __le16 ftype
= mgmt
->frame_control
&
632 cpu_to_le16(IEEE80211_FCTL_FTYPE
| IEEE80211_FCTL_STYPE
);
635 trace_cfg80211_rx_mgmt(wdev
, freq
, sig_mbm
);
636 stype
= (le16_to_cpu(mgmt
->frame_control
) & IEEE80211_FCTL_STYPE
) >> 4;
638 if (!(stypes
->rx
& BIT(stype
))) {
639 trace_cfg80211_return_bool(false);
643 data
= buf
+ ieee80211_hdrlen(mgmt
->frame_control
);
644 data_len
= len
- ieee80211_hdrlen(mgmt
->frame_control
);
646 spin_lock_bh(&wdev
->mgmt_registrations_lock
);
648 list_for_each_entry(reg
, &wdev
->mgmt_registrations
, list
) {
649 if (reg
->frame_type
!= ftype
)
652 if (reg
->match_len
> data_len
)
655 if (memcmp(reg
->match
, data
, reg
->match_len
))
660 /* Indicate the received Action frame to user space */
661 if (nl80211_send_mgmt(rdev
, wdev
, reg
->nlportid
,
663 buf
, len
, flags
, gfp
))
670 spin_unlock_bh(&wdev
->mgmt_registrations_lock
);
672 trace_cfg80211_return_bool(result
);
675 EXPORT_SYMBOL(cfg80211_rx_mgmt
);
677 void cfg80211_dfs_channels_update_work(struct work_struct
*work
)
679 struct delayed_work
*delayed_work
;
680 struct cfg80211_registered_device
*rdev
;
681 struct cfg80211_chan_def chandef
;
682 struct ieee80211_supported_band
*sband
;
683 struct ieee80211_channel
*c
;
685 bool check_again
= false;
686 unsigned long timeout
, next_time
= 0;
689 delayed_work
= container_of(work
, struct delayed_work
, work
);
690 rdev
= container_of(delayed_work
, struct cfg80211_registered_device
,
691 dfs_update_channels_wk
);
692 wiphy
= &rdev
->wiphy
;
695 for (bandid
= 0; bandid
< IEEE80211_NUM_BANDS
; bandid
++) {
696 sband
= wiphy
->bands
[bandid
];
700 for (i
= 0; i
< sband
->n_channels
; i
++) {
701 c
= &sband
->channels
[i
];
703 if (c
->dfs_state
!= NL80211_DFS_UNAVAILABLE
)
706 timeout
= c
->dfs_state_entered
+ msecs_to_jiffies(
707 IEEE80211_DFS_MIN_NOP_TIME_MS
);
709 if (time_after_eq(jiffies
, timeout
)) {
710 c
->dfs_state
= NL80211_DFS_USABLE
;
711 c
->dfs_state_entered
= jiffies
;
713 cfg80211_chandef_create(&chandef
, c
,
716 nl80211_radar_notify(rdev
, &chandef
,
717 NL80211_RADAR_NOP_FINISHED
,
723 next_time
= timeout
- jiffies
;
725 next_time
= min(next_time
, timeout
- jiffies
);
731 /* reschedule if there are other channels waiting to be cleared again */
733 queue_delayed_work(cfg80211_wq
, &rdev
->dfs_update_channels_wk
,
738 void cfg80211_radar_event(struct wiphy
*wiphy
,
739 struct cfg80211_chan_def
*chandef
,
742 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
743 unsigned long timeout
;
745 trace_cfg80211_radar_event(wiphy
, chandef
);
747 /* only set the chandef supplied channel to unavailable, in
748 * case the radar is detected on only one of multiple channels
749 * spanned by the chandef.
751 cfg80211_set_dfs_state(wiphy
, chandef
, NL80211_DFS_UNAVAILABLE
);
753 timeout
= msecs_to_jiffies(IEEE80211_DFS_MIN_NOP_TIME_MS
);
754 queue_delayed_work(cfg80211_wq
, &rdev
->dfs_update_channels_wk
,
757 nl80211_radar_notify(rdev
, chandef
, NL80211_RADAR_DETECTED
, NULL
, gfp
);
759 EXPORT_SYMBOL(cfg80211_radar_event
);
761 void cfg80211_cac_event(struct net_device
*netdev
,
762 const struct cfg80211_chan_def
*chandef
,
763 enum nl80211_radar_event event
, gfp_t gfp
)
765 struct wireless_dev
*wdev
= netdev
->ieee80211_ptr
;
766 struct wiphy
*wiphy
= wdev
->wiphy
;
767 struct cfg80211_registered_device
*rdev
= wiphy_to_dev(wiphy
);
768 unsigned long timeout
;
770 trace_cfg80211_cac_event(netdev
, event
);
772 if (WARN_ON(!wdev
->cac_started
))
775 if (WARN_ON(!wdev
->chandef
.chan
))
779 case NL80211_RADAR_CAC_FINISHED
:
780 timeout
= wdev
->cac_start_time
+
781 msecs_to_jiffies(wdev
->cac_time_ms
);
782 WARN_ON(!time_after_eq(jiffies
, timeout
));
783 cfg80211_set_dfs_state(wiphy
, chandef
, NL80211_DFS_AVAILABLE
);
785 case NL80211_RADAR_CAC_ABORTED
:
791 wdev
->cac_started
= false;
793 nl80211_radar_notify(rdev
, chandef
, event
, netdev
, gfp
);
795 EXPORT_SYMBOL(cfg80211_cac_event
);