1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
4 #include <linux/kernel.h>
5 #include <linux/module.h>
6 #include <linux/slab.h>
7 #include <linux/nospec.h>
16 #include "qlink_util.h"
19 qtnf_event_handle_sta_assoc(struct qtnf_wmac
*mac
, struct qtnf_vif
*vif
,
20 const struct qlink_event_sta_assoc
*sta_assoc
,
25 struct station_info
*sinfo
;
29 const struct qlink_tlv_hdr
*tlv
;
32 if (unlikely(len
< sizeof(*sta_assoc
))) {
33 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
34 mac
->macid
, vif
->vifid
, len
, sizeof(*sta_assoc
));
38 if (vif
->wdev
.iftype
!= NL80211_IFTYPE_AP
) {
39 pr_err("VIF%u.%u: STA_ASSOC event when not in AP mode\n",
40 mac
->macid
, vif
->vifid
);
44 sinfo
= kzalloc(sizeof(*sinfo
), GFP_KERNEL
);
48 sta_addr
= sta_assoc
->sta_addr
;
49 frame_control
= le16_to_cpu(sta_assoc
->frame_control
);
51 pr_debug("VIF%u.%u: MAC:%pM FC:%x\n", mac
->macid
, vif
->vifid
, sta_addr
,
54 qtnf_sta_list_add(vif
, sta_addr
);
56 sinfo
->assoc_req_ies
= NULL
;
57 sinfo
->assoc_req_ies_len
= 0;
58 sinfo
->generation
= vif
->generation
;
60 payload_len
= len
- sizeof(*sta_assoc
);
62 qlink_for_each_tlv(tlv
, sta_assoc
->ies
, payload_len
) {
63 tlv_type
= le16_to_cpu(tlv
->type
);
64 tlv_value_len
= le16_to_cpu(tlv
->len
);
66 if (tlv_type
== QTN_TLV_ID_IE_SET
) {
67 const struct qlink_tlv_ie_set
*ie_set
;
71 (sizeof(*ie_set
) - sizeof(ie_set
->hdr
))) {
76 ie_set
= (const struct qlink_tlv_ie_set
*)tlv
;
77 ie_len
= tlv_value_len
-
78 (sizeof(*ie_set
) - sizeof(ie_set
->hdr
));
80 if (ie_set
->type
== QLINK_IE_SET_ASSOC_REQ
&& ie_len
) {
81 sinfo
->assoc_req_ies
= ie_set
->ie_data
;
82 sinfo
->assoc_req_ies_len
= ie_len
;
87 if (!qlink_tlv_parsing_ok(tlv
, sta_assoc
->ies
, payload_len
)) {
88 pr_err("Malformed TLV buffer\n");
93 cfg80211_new_sta(vif
->netdev
, sta_assoc
->sta_addr
, sinfo
,
102 qtnf_event_handle_sta_deauth(struct qtnf_wmac
*mac
, struct qtnf_vif
*vif
,
103 const struct qlink_event_sta_deauth
*sta_deauth
,
109 if (unlikely(len
< sizeof(*sta_deauth
))) {
110 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
111 mac
->macid
, vif
->vifid
, len
,
112 sizeof(struct qlink_event_sta_deauth
));
116 if (vif
->wdev
.iftype
!= NL80211_IFTYPE_AP
) {
117 pr_err("VIF%u.%u: STA_DEAUTH event when not in AP mode\n",
118 mac
->macid
, vif
->vifid
);
122 sta_addr
= sta_deauth
->sta_addr
;
123 reason
= le16_to_cpu(sta_deauth
->reason
);
125 pr_debug("VIF%u.%u: MAC:%pM reason:%x\n", mac
->macid
, vif
->vifid
,
128 if (qtnf_sta_list_del(vif
, sta_addr
))
129 cfg80211_del_sta(vif
->netdev
, sta_deauth
->sta_addr
,
136 qtnf_event_handle_bss_join(struct qtnf_vif
*vif
,
137 const struct qlink_event_bss_join
*join_info
,
140 struct wiphy
*wiphy
= priv_to_wiphy(vif
->mac
);
141 enum ieee80211_statuscode status
= le16_to_cpu(join_info
->status
);
142 struct cfg80211_chan_def chandef
;
143 struct cfg80211_bss
*bss
= NULL
;
148 const struct qlink_tlv_hdr
*tlv
;
149 const u8
*rsp_ies
= NULL
;
150 size_t rsp_ies_len
= 0;
152 if (unlikely(len
< sizeof(*join_info
))) {
153 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
154 vif
->mac
->macid
, vif
->vifid
, len
,
155 sizeof(struct qlink_event_bss_join
));
159 if (vif
->wdev
.iftype
!= NL80211_IFTYPE_STATION
) {
160 pr_err("VIF%u.%u: BSS_JOIN event when not in STA mode\n",
161 vif
->mac
->macid
, vif
->vifid
);
165 pr_debug("VIF%u.%u: BSSID:%pM chan:%u status:%u\n",
166 vif
->mac
->macid
, vif
->vifid
, join_info
->bssid
,
167 le16_to_cpu(join_info
->chan
.chan
.center_freq
), status
);
169 if (status
!= WLAN_STATUS_SUCCESS
)
172 qlink_chandef_q2cfg(wiphy
, &join_info
->chan
, &chandef
);
173 if (!cfg80211_chandef_valid(&chandef
)) {
174 pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n",
175 vif
->mac
->macid
, vif
->vifid
,
176 chandef
.chan
? chandef
.chan
->center_freq
: 0,
177 chandef
.center_freq1
,
178 chandef
.center_freq2
,
180 status
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
184 bss
= cfg80211_get_bss(wiphy
, chandef
.chan
, join_info
->bssid
,
185 NULL
, 0, IEEE80211_BSS_TYPE_ESS
,
186 IEEE80211_PRIVACY_ANY
);
188 pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n",
189 vif
->mac
->macid
, vif
->vifid
,
190 join_info
->bssid
, chandef
.chan
->hw_value
);
192 if (!vif
->wdev
.u
.client
.ssid_len
) {
193 pr_warn("VIF%u.%u: SSID unknown for BSS:%pM\n",
194 vif
->mac
->macid
, vif
->vifid
,
196 status
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
200 ie
= kzalloc(2 + vif
->wdev
.u
.client
.ssid_len
, GFP_KERNEL
);
202 pr_warn("VIF%u.%u: IE alloc failed for BSS:%pM\n",
203 vif
->mac
->macid
, vif
->vifid
,
205 status
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
209 ie
[0] = WLAN_EID_SSID
;
210 ie
[1] = vif
->wdev
.u
.client
.ssid_len
;
211 memcpy(ie
+ 2, vif
->wdev
.u
.client
.ssid
,
212 vif
->wdev
.u
.client
.ssid_len
);
214 bss
= cfg80211_inform_bss(wiphy
, chandef
.chan
,
215 CFG80211_BSS_FTYPE_UNKNOWN
,
217 WLAN_CAPABILITY_ESS
, 100,
218 ie
, 2 + vif
->wdev
.u
.client
.ssid_len
,
221 pr_warn("VIF%u.%u: can't connect to unknown BSS: %pM\n",
222 vif
->mac
->macid
, vif
->vifid
,
224 status
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
229 payload_len
= len
- sizeof(*join_info
);
231 qlink_for_each_tlv(tlv
, join_info
->ies
, payload_len
) {
232 tlv_type
= le16_to_cpu(tlv
->type
);
233 tlv_value_len
= le16_to_cpu(tlv
->len
);
235 if (tlv_type
== QTN_TLV_ID_IE_SET
) {
236 const struct qlink_tlv_ie_set
*ie_set
;
240 (sizeof(*ie_set
) - sizeof(ie_set
->hdr
))) {
241 pr_warn("invalid IE_SET TLV\n");
242 status
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
246 ie_set
= (const struct qlink_tlv_ie_set
*)tlv
;
247 ie_len
= tlv_value_len
-
248 (sizeof(*ie_set
) - sizeof(ie_set
->hdr
));
250 switch (ie_set
->type
) {
251 case QLINK_IE_SET_ASSOC_RESP
:
253 rsp_ies
= ie_set
->ie_data
;
254 rsp_ies_len
= ie_len
;
258 pr_warn("unexpected IE type: %u\n",
265 if (!qlink_tlv_parsing_ok(tlv
, join_info
->ies
, payload_len
))
266 pr_warn("Malformed TLV buffer\n");
268 cfg80211_connect_result(vif
->netdev
, join_info
->bssid
, NULL
, 0, rsp_ies
,
269 rsp_ies_len
, status
, GFP_KERNEL
);
271 if (!ether_addr_equal(vif
->bssid
, join_info
->bssid
))
272 ether_addr_copy(vif
->bssid
, join_info
->bssid
);
273 cfg80211_put_bss(wiphy
, bss
);
276 if (status
== WLAN_STATUS_SUCCESS
)
277 netif_carrier_on(vif
->netdev
);
284 qtnf_event_handle_bss_leave(struct qtnf_vif
*vif
,
285 const struct qlink_event_bss_leave
*leave_info
,
288 if (unlikely(len
< sizeof(*leave_info
))) {
289 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
290 vif
->mac
->macid
, vif
->vifid
, len
,
291 sizeof(struct qlink_event_bss_leave
));
295 if (vif
->wdev
.iftype
!= NL80211_IFTYPE_STATION
) {
296 pr_err("VIF%u.%u: BSS_LEAVE event when not in STA mode\n",
297 vif
->mac
->macid
, vif
->vifid
);
301 pr_debug("VIF%u.%u: disconnected\n", vif
->mac
->macid
, vif
->vifid
);
303 cfg80211_disconnected(vif
->netdev
, le16_to_cpu(leave_info
->reason
),
304 NULL
, 0, 0, GFP_KERNEL
);
305 netif_carrier_off(vif
->netdev
);
311 qtnf_event_handle_mgmt_received(struct qtnf_vif
*vif
,
312 const struct qlink_event_rxmgmt
*rxmgmt
,
315 const size_t min_len
= sizeof(*rxmgmt
) +
316 sizeof(struct ieee80211_hdr_3addr
);
317 const struct ieee80211_hdr_3addr
*frame
= (void *)rxmgmt
->frame_data
;
318 const u16 frame_len
= len
- sizeof(*rxmgmt
);
319 enum nl80211_rxmgmt_flags flags
= 0;
321 if (unlikely(len
< min_len
)) {
322 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
323 vif
->mac
->macid
, vif
->vifid
, len
, min_len
);
327 if (le32_to_cpu(rxmgmt
->flags
) & QLINK_RXMGMT_FLAG_ANSWERED
)
328 flags
|= NL80211_RXMGMT_FLAG_ANSWERED
;
330 pr_debug("%s LEN:%u FC:%.4X SA:%pM\n", vif
->netdev
->name
, frame_len
,
331 le16_to_cpu(frame
->frame_control
), frame
->addr2
);
333 cfg80211_rx_mgmt(&vif
->wdev
, le32_to_cpu(rxmgmt
->freq
), rxmgmt
->sig_dbm
,
334 rxmgmt
->frame_data
, frame_len
, flags
);
340 qtnf_event_handle_scan_results(struct qtnf_vif
*vif
,
341 const struct qlink_event_scan_result
*sr
,
344 struct cfg80211_bss
*bss
;
345 struct ieee80211_channel
*channel
;
346 struct wiphy
*wiphy
= priv_to_wiphy(vif
->mac
);
347 enum cfg80211_bss_frame_type frame_type
= CFG80211_BSS_FTYPE_UNKNOWN
;
351 const struct qlink_tlv_hdr
*tlv
;
352 const u8
*ies
= NULL
;
355 if (len
< sizeof(*sr
)) {
356 pr_err("VIF%u.%u: payload is too short\n", vif
->mac
->macid
,
361 channel
= ieee80211_get_channel(wiphy
, le16_to_cpu(sr
->freq
));
363 pr_err("VIF%u.%u: channel at %u MHz not found\n",
364 vif
->mac
->macid
, vif
->vifid
, le16_to_cpu(sr
->freq
));
368 payload_len
= len
- sizeof(*sr
);
370 qlink_for_each_tlv(tlv
, sr
->payload
, payload_len
) {
371 tlv_type
= le16_to_cpu(tlv
->type
);
372 tlv_value_len
= le16_to_cpu(tlv
->len
);
374 if (tlv_type
== QTN_TLV_ID_IE_SET
) {
375 const struct qlink_tlv_ie_set
*ie_set
;
379 (sizeof(*ie_set
) - sizeof(ie_set
->hdr
)))
382 ie_set
= (const struct qlink_tlv_ie_set
*)tlv
;
383 ie_len
= tlv_value_len
-
384 (sizeof(*ie_set
) - sizeof(ie_set
->hdr
));
386 switch (ie_set
->type
) {
387 case QLINK_IE_SET_BEACON_IES
:
388 frame_type
= CFG80211_BSS_FTYPE_BEACON
;
390 case QLINK_IE_SET_PROBE_RESP_IES
:
391 frame_type
= CFG80211_BSS_FTYPE_PRESP
;
394 frame_type
= CFG80211_BSS_FTYPE_UNKNOWN
;
398 ies
= ie_set
->ie_data
;
404 if (!qlink_tlv_parsing_ok(tlv
, sr
->payload
, payload_len
))
407 bss
= cfg80211_inform_bss(wiphy
, channel
, frame_type
,
408 sr
->bssid
, get_unaligned_le64(&sr
->tsf
),
409 le16_to_cpu(sr
->capab
),
410 le16_to_cpu(sr
->bintval
), ies
, ies_len
,
411 DBM_TO_MBM(sr
->sig_dbm
), GFP_KERNEL
);
415 cfg80211_put_bss(wiphy
, bss
);
421 qtnf_event_handle_scan_complete(struct qtnf_wmac
*mac
,
422 const struct qlink_event_scan_complete
*status
,
425 if (len
< sizeof(*status
)) {
426 pr_err("MAC%u: payload is too short\n", mac
->macid
);
430 qtnf_scan_done(mac
, le32_to_cpu(status
->flags
) & QLINK_SCAN_ABORTED
);
436 qtnf_event_handle_freq_change(struct qtnf_wmac
*mac
,
437 const struct qlink_event_freq_change
*data
,
440 struct wiphy
*wiphy
= priv_to_wiphy(mac
);
441 struct cfg80211_chan_def chandef
;
442 struct qtnf_vif
*vif
;
445 if (len
< sizeof(*data
)) {
446 pr_err("MAC%u: payload is too short\n", mac
->macid
);
450 if (!wiphy
->registered
)
453 qlink_chandef_q2cfg(wiphy
, &data
->chan
, &chandef
);
455 if (!cfg80211_chandef_valid(&chandef
)) {
456 pr_err("MAC%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n",
457 mac
->macid
, chandef
.chan
->center_freq
,
458 chandef
.center_freq1
, chandef
.center_freq2
,
463 pr_debug("MAC%d: new channel ieee=%u freq1=%u freq2=%u bw=%u\n",
464 mac
->macid
, chandef
.chan
->hw_value
, chandef
.center_freq1
,
465 chandef
.center_freq2
, chandef
.width
);
467 for (i
= 0; i
< QTNF_MAX_INTF
; i
++) {
468 vif
= &mac
->iflist
[i
];
470 if (vif
->wdev
.iftype
== NL80211_IFTYPE_UNSPECIFIED
)
473 if (vif
->wdev
.iftype
== NL80211_IFTYPE_STATION
&&
474 !vif
->wdev
.connected
)
480 wiphy_lock(priv_to_wiphy(vif
->mac
));
481 cfg80211_ch_switch_notify(vif
->netdev
, &chandef
, 0);
482 wiphy_unlock(priv_to_wiphy(vif
->mac
));
488 static int qtnf_event_handle_radar(struct qtnf_vif
*vif
,
489 const struct qlink_event_radar
*ev
,
492 struct wiphy
*wiphy
= priv_to_wiphy(vif
->mac
);
493 struct cfg80211_chan_def chandef
;
495 if (len
< sizeof(*ev
)) {
496 pr_err("MAC%u: payload is too short\n", vif
->mac
->macid
);
500 if (!wiphy
->registered
|| !vif
->netdev
)
503 qlink_chandef_q2cfg(wiphy
, &ev
->chan
, &chandef
);
505 if (!cfg80211_chandef_valid(&chandef
)) {
506 pr_err("MAC%u: bad channel f1=%u f2=%u bw=%u\n",
508 chandef
.center_freq1
, chandef
.center_freq2
,
513 pr_info("%s: radar event=%u f1=%u f2=%u bw=%u\n",
514 vif
->netdev
->name
, ev
->event
,
515 chandef
.center_freq1
, chandef
.center_freq2
,
519 case QLINK_RADAR_DETECTED
:
520 cfg80211_radar_event(wiphy
, &chandef
, GFP_KERNEL
);
522 case QLINK_RADAR_CAC_FINISHED
:
523 if (!vif
->wdev
.links
[0].cac_started
)
526 cfg80211_cac_event(vif
->netdev
, &chandef
,
527 NL80211_RADAR_CAC_FINISHED
, GFP_KERNEL
, 0);
529 case QLINK_RADAR_CAC_ABORTED
:
530 if (!vif
->wdev
.links
[0].cac_started
)
533 cfg80211_cac_event(vif
->netdev
, &chandef
,
534 NL80211_RADAR_CAC_ABORTED
, GFP_KERNEL
, 0);
536 case QLINK_RADAR_CAC_STARTED
:
537 if (vif
->wdev
.links
[0].cac_started
)
540 if (!wiphy_ext_feature_isset(wiphy
,
541 NL80211_EXT_FEATURE_DFS_OFFLOAD
))
544 cfg80211_cac_event(vif
->netdev
, &chandef
,
545 NL80211_RADAR_CAC_STARTED
, GFP_KERNEL
, 0);
548 pr_warn("%s: unhandled radar event %u\n",
549 vif
->netdev
->name
, ev
->event
);
557 qtnf_event_handle_external_auth(struct qtnf_vif
*vif
,
558 const struct qlink_event_external_auth
*ev
,
561 struct cfg80211_external_auth_params auth
= {0};
562 struct wiphy
*wiphy
= priv_to_wiphy(vif
->mac
);
565 if (len
< sizeof(*ev
)) {
566 pr_err("MAC%u: payload is too short\n", vif
->mac
->macid
);
570 if (!wiphy
->registered
|| !vif
->netdev
)
574 int len
= clamp_val(ev
->ssid_len
, 0, IEEE80211_MAX_SSID_LEN
);
576 memcpy(auth
.ssid
.ssid
, ev
->ssid
, len
);
577 auth
.ssid
.ssid_len
= len
;
580 auth
.key_mgmt_suite
= le32_to_cpu(ev
->akm_suite
);
581 ether_addr_copy(auth
.bssid
, ev
->bssid
);
582 auth
.action
= ev
->action
;
584 pr_debug("%s: external SAE processing: bss=%pM action=%u akm=%u\n",
585 vif
->netdev
->name
, auth
.bssid
, auth
.action
,
586 auth
.key_mgmt_suite
);
588 ret
= cfg80211_external_auth_request(vif
->netdev
, &auth
, GFP_KERNEL
);
590 pr_warn("failed to offload external auth request\n");
596 qtnf_event_handle_mic_failure(struct qtnf_vif
*vif
,
597 const struct qlink_event_mic_failure
*mic_ev
,
600 struct wiphy
*wiphy
= priv_to_wiphy(vif
->mac
);
603 if (len
< sizeof(*mic_ev
)) {
604 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
605 vif
->mac
->macid
, vif
->vifid
, len
,
606 sizeof(struct qlink_event_mic_failure
));
610 if (!wiphy
->registered
|| !vif
->netdev
)
613 if (vif
->wdev
.iftype
!= NL80211_IFTYPE_STATION
) {
614 pr_err("VIF%u.%u: MIC_FAILURE event when not in STA mode\n",
615 vif
->mac
->macid
, vif
->vifid
);
619 pairwise
= mic_ev
->pairwise
?
620 NL80211_KEYTYPE_PAIRWISE
: NL80211_KEYTYPE_GROUP
;
622 pr_info("%s: MIC error: src=%pM key_index=%u pairwise=%u\n",
623 vif
->netdev
->name
, mic_ev
->src
, mic_ev
->key_index
, pairwise
);
625 cfg80211_michael_mic_failure(vif
->netdev
, mic_ev
->src
, pairwise
,
626 mic_ev
->key_index
, NULL
, GFP_KERNEL
);
632 qtnf_event_handle_update_owe(struct qtnf_vif
*vif
,
633 const struct qlink_event_update_owe
*owe_ev
,
636 struct wiphy
*wiphy
= priv_to_wiphy(vif
->mac
);
637 struct cfg80211_update_owe_info owe_info
= {};
638 const u16 ie_len
= len
- sizeof(*owe_ev
);
641 if (len
< sizeof(*owe_ev
)) {
642 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
643 vif
->mac
->macid
, vif
->vifid
, len
,
644 sizeof(struct qlink_event_update_owe
));
648 if (!wiphy
->registered
|| !vif
->netdev
)
651 if (vif
->wdev
.iftype
!= NL80211_IFTYPE_AP
) {
652 pr_err("VIF%u.%u: UPDATE_OWE event when not in AP mode\n",
653 vif
->mac
->macid
, vif
->vifid
);
657 ie
= kzalloc(ie_len
, GFP_KERNEL
);
661 memcpy(owe_info
.peer
, owe_ev
->peer
, ETH_ALEN
);
662 memcpy(ie
, owe_ev
->ies
, ie_len
);
663 owe_info
.ie_len
= ie_len
;
665 owe_info
.assoc_link_id
= -1;
667 pr_info("%s: external OWE processing: peer=%pM\n",
668 vif
->netdev
->name
, owe_ev
->peer
);
670 cfg80211_update_owe_info_event(vif
->netdev
, &owe_info
, GFP_KERNEL
);
676 static int qtnf_event_parse(struct qtnf_wmac
*mac
,
677 const struct sk_buff
*event_skb
)
679 const struct qlink_event
*event
;
680 struct qtnf_vif
*vif
= NULL
;
686 event
= (const struct qlink_event
*)event_skb
->data
;
687 event_id
= le16_to_cpu(event
->event_id
);
688 event_len
= le16_to_cpu(event
->mhdr
.len
);
690 if (event
->vifid
>= QTNF_MAX_INTF
) {
691 pr_err("invalid vif(%u)\n", event
->vifid
);
695 vifid
= array_index_nospec(event
->vifid
, QTNF_MAX_INTF
);
696 vif
= &mac
->iflist
[vifid
];
699 case QLINK_EVENT_STA_ASSOCIATED
:
700 ret
= qtnf_event_handle_sta_assoc(mac
, vif
, (const void *)event
,
703 case QLINK_EVENT_STA_DEAUTH
:
704 ret
= qtnf_event_handle_sta_deauth(mac
, vif
,
708 case QLINK_EVENT_MGMT_RECEIVED
:
709 ret
= qtnf_event_handle_mgmt_received(vif
, (const void *)event
,
712 case QLINK_EVENT_SCAN_RESULTS
:
713 ret
= qtnf_event_handle_scan_results(vif
, (const void *)event
,
716 case QLINK_EVENT_SCAN_COMPLETE
:
717 ret
= qtnf_event_handle_scan_complete(mac
, (const void *)event
,
720 case QLINK_EVENT_BSS_JOIN
:
721 ret
= qtnf_event_handle_bss_join(vif
, (const void *)event
,
724 case QLINK_EVENT_BSS_LEAVE
:
725 ret
= qtnf_event_handle_bss_leave(vif
, (const void *)event
,
728 case QLINK_EVENT_FREQ_CHANGE
:
729 ret
= qtnf_event_handle_freq_change(mac
, (const void *)event
,
732 case QLINK_EVENT_RADAR
:
733 ret
= qtnf_event_handle_radar(vif
, (const void *)event
,
736 case QLINK_EVENT_EXTERNAL_AUTH
:
737 ret
= qtnf_event_handle_external_auth(vif
, (const void *)event
,
740 case QLINK_EVENT_MIC_FAILURE
:
741 ret
= qtnf_event_handle_mic_failure(vif
, (const void *)event
,
744 case QLINK_EVENT_UPDATE_OWE
:
745 ret
= qtnf_event_handle_update_owe(vif
, (const void *)event
,
749 pr_warn("unknown event type: %x\n", event_id
);
756 static int qtnf_event_process_skb(struct qtnf_bus
*bus
,
757 const struct sk_buff
*skb
)
759 const struct qlink_event
*event
;
760 struct qtnf_wmac
*mac
;
763 if (unlikely(!skb
|| skb
->len
< sizeof(*event
))) {
764 pr_err("invalid event buffer\n");
768 event
= (struct qlink_event
*)skb
->data
;
770 mac
= qtnf_core_get_mac(bus
, event
->macid
);
772 pr_debug("new event id:%x len:%u mac:%u vif:%u\n",
773 le16_to_cpu(event
->event_id
), le16_to_cpu(event
->mhdr
.len
),
774 event
->macid
, event
->vifid
);
780 res
= qtnf_event_parse(mac
, skb
);
786 void qtnf_event_work_handler(struct work_struct
*work
)
788 struct qtnf_bus
*bus
= container_of(work
, struct qtnf_bus
, event_work
);
789 struct sk_buff_head
*event_queue
= &bus
->trans
.event_queue
;
790 struct sk_buff
*current_event_skb
= skb_dequeue(event_queue
);
792 while (current_event_skb
) {
793 qtnf_event_process_skb(bus
, current_event_skb
);
794 dev_kfree_skb_any(current_event_skb
);
795 current_event_skb
= skb_dequeue(event_queue
);