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>
15 #include "qlink_util.h"
18 qtnf_event_handle_sta_assoc(struct qtnf_wmac
*mac
, struct qtnf_vif
*vif
,
19 const struct qlink_event_sta_assoc
*sta_assoc
,
24 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
);
61 tlv
= (const struct qlink_tlv_hdr
*)sta_assoc
->ies
;
63 while (payload_len
>= sizeof(*tlv
)) {
64 tlv_type
= le16_to_cpu(tlv
->type
);
65 tlv_value_len
= le16_to_cpu(tlv
->len
);
66 tlv_full_len
= tlv_value_len
+ sizeof(struct qlink_tlv_hdr
);
68 if (tlv_full_len
> payload_len
) {
73 if (tlv_type
== QTN_TLV_ID_IE_SET
) {
74 const struct qlink_tlv_ie_set
*ie_set
;
77 if (payload_len
< sizeof(*ie_set
)) {
82 ie_set
= (const struct qlink_tlv_ie_set
*)tlv
;
83 ie_len
= tlv_value_len
-
84 (sizeof(*ie_set
) - sizeof(ie_set
->hdr
));
86 if (ie_set
->type
== QLINK_IE_SET_ASSOC_REQ
&& ie_len
) {
87 sinfo
->assoc_req_ies
= ie_set
->ie_data
;
88 sinfo
->assoc_req_ies_len
= ie_len
;
92 payload_len
-= tlv_full_len
;
93 tlv
= (struct qlink_tlv_hdr
*)(tlv
->val
+ tlv_value_len
);
101 cfg80211_new_sta(vif
->netdev
, sta_assoc
->sta_addr
, sinfo
,
110 qtnf_event_handle_sta_deauth(struct qtnf_wmac
*mac
, struct qtnf_vif
*vif
,
111 const struct qlink_event_sta_deauth
*sta_deauth
,
117 if (unlikely(len
< sizeof(*sta_deauth
))) {
118 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
119 mac
->macid
, vif
->vifid
, len
,
120 sizeof(struct qlink_event_sta_deauth
));
124 if (vif
->wdev
.iftype
!= NL80211_IFTYPE_AP
) {
125 pr_err("VIF%u.%u: STA_DEAUTH event when not in AP mode\n",
126 mac
->macid
, vif
->vifid
);
130 sta_addr
= sta_deauth
->sta_addr
;
131 reason
= le16_to_cpu(sta_deauth
->reason
);
133 pr_debug("VIF%u.%u: MAC:%pM reason:%x\n", mac
->macid
, vif
->vifid
,
136 if (qtnf_sta_list_del(vif
, sta_addr
))
137 cfg80211_del_sta(vif
->netdev
, sta_deauth
->sta_addr
,
144 qtnf_event_handle_bss_join(struct qtnf_vif
*vif
,
145 const struct qlink_event_bss_join
*join_info
,
148 struct wiphy
*wiphy
= priv_to_wiphy(vif
->mac
);
149 enum ieee80211_statuscode status
= le16_to_cpu(join_info
->status
);
150 struct cfg80211_chan_def chandef
;
151 struct cfg80211_bss
*bss
= NULL
;
157 const struct qlink_tlv_hdr
*tlv
;
158 const u8
*rsp_ies
= NULL
;
159 size_t rsp_ies_len
= 0;
161 if (unlikely(len
< sizeof(*join_info
))) {
162 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
163 vif
->mac
->macid
, vif
->vifid
, len
,
164 sizeof(struct qlink_event_bss_join
));
168 if (vif
->wdev
.iftype
!= NL80211_IFTYPE_STATION
) {
169 pr_err("VIF%u.%u: BSS_JOIN event when not in STA mode\n",
170 vif
->mac
->macid
, vif
->vifid
);
174 pr_debug("VIF%u.%u: BSSID:%pM status:%u\n",
175 vif
->mac
->macid
, vif
->vifid
, join_info
->bssid
, status
);
177 if (status
!= WLAN_STATUS_SUCCESS
)
180 qlink_chandef_q2cfg(wiphy
, &join_info
->chan
, &chandef
);
181 if (!cfg80211_chandef_valid(&chandef
)) {
182 pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n",
183 vif
->mac
->macid
, vif
->vifid
,
184 chandef
.chan
->center_freq
,
185 chandef
.center_freq1
,
186 chandef
.center_freq2
,
188 status
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
192 bss
= cfg80211_get_bss(wiphy
, chandef
.chan
, join_info
->bssid
,
193 NULL
, 0, IEEE80211_BSS_TYPE_ESS
,
194 IEEE80211_PRIVACY_ANY
);
196 pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n",
197 vif
->mac
->macid
, vif
->vifid
,
198 join_info
->bssid
, chandef
.chan
->hw_value
);
200 if (!vif
->wdev
.ssid_len
) {
201 pr_warn("VIF%u.%u: SSID unknown for BSS:%pM\n",
202 vif
->mac
->macid
, vif
->vifid
,
204 status
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
208 ie
= kzalloc(2 + vif
->wdev
.ssid_len
, GFP_KERNEL
);
210 pr_warn("VIF%u.%u: IE alloc failed for BSS:%pM\n",
211 vif
->mac
->macid
, vif
->vifid
,
213 status
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
217 ie
[0] = WLAN_EID_SSID
;
218 ie
[1] = vif
->wdev
.ssid_len
;
219 memcpy(ie
+ 2, vif
->wdev
.ssid
, vif
->wdev
.ssid_len
);
221 bss
= cfg80211_inform_bss(wiphy
, chandef
.chan
,
222 CFG80211_BSS_FTYPE_UNKNOWN
,
224 WLAN_CAPABILITY_ESS
, 100,
225 ie
, 2 + vif
->wdev
.ssid_len
,
228 pr_warn("VIF%u.%u: can't connect to unknown BSS: %pM\n",
229 vif
->mac
->macid
, vif
->vifid
,
231 status
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
236 payload_len
= len
- sizeof(*join_info
);
237 tlv
= (struct qlink_tlv_hdr
*)join_info
->ies
;
239 while (payload_len
>= sizeof(struct qlink_tlv_hdr
)) {
240 tlv_type
= le16_to_cpu(tlv
->type
);
241 tlv_value_len
= le16_to_cpu(tlv
->len
);
242 tlv_full_len
= tlv_value_len
+ sizeof(struct qlink_tlv_hdr
);
244 if (payload_len
< tlv_full_len
) {
245 pr_warn("invalid %u TLV\n", tlv_type
);
246 status
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
250 if (tlv_type
== QTN_TLV_ID_IE_SET
) {
251 const struct qlink_tlv_ie_set
*ie_set
;
254 if (payload_len
< sizeof(*ie_set
)) {
255 pr_warn("invalid IE_SET TLV\n");
256 status
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
260 ie_set
= (const struct qlink_tlv_ie_set
*)tlv
;
261 ie_len
= tlv_value_len
-
262 (sizeof(*ie_set
) - sizeof(ie_set
->hdr
));
264 switch (ie_set
->type
) {
265 case QLINK_IE_SET_ASSOC_RESP
:
267 rsp_ies
= ie_set
->ie_data
;
268 rsp_ies_len
= ie_len
;
272 pr_warn("unexpected IE type: %u\n",
278 payload_len
-= tlv_full_len
;
279 tlv
= (struct qlink_tlv_hdr
*)(tlv
->val
+ tlv_value_len
);
283 pr_warn("VIF%u.%u: unexpected remaining payload: %zu\n",
284 vif
->mac
->macid
, vif
->vifid
, payload_len
);
287 cfg80211_connect_result(vif
->netdev
, join_info
->bssid
, NULL
, 0, rsp_ies
,
288 rsp_ies_len
, status
, GFP_KERNEL
);
290 if (!ether_addr_equal(vif
->bssid
, join_info
->bssid
))
291 ether_addr_copy(vif
->bssid
, join_info
->bssid
);
292 cfg80211_put_bss(wiphy
, bss
);
295 if (status
== WLAN_STATUS_SUCCESS
)
296 netif_carrier_on(vif
->netdev
);
303 qtnf_event_handle_bss_leave(struct qtnf_vif
*vif
,
304 const struct qlink_event_bss_leave
*leave_info
,
307 if (unlikely(len
< sizeof(*leave_info
))) {
308 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
309 vif
->mac
->macid
, vif
->vifid
, len
,
310 sizeof(struct qlink_event_bss_leave
));
314 if (vif
->wdev
.iftype
!= NL80211_IFTYPE_STATION
) {
315 pr_err("VIF%u.%u: BSS_LEAVE event when not in STA mode\n",
316 vif
->mac
->macid
, vif
->vifid
);
320 pr_debug("VIF%u.%u: disconnected\n", vif
->mac
->macid
, vif
->vifid
);
322 cfg80211_disconnected(vif
->netdev
, le16_to_cpu(leave_info
->reason
),
323 NULL
, 0, 0, GFP_KERNEL
);
324 netif_carrier_off(vif
->netdev
);
330 qtnf_event_handle_mgmt_received(struct qtnf_vif
*vif
,
331 const struct qlink_event_rxmgmt
*rxmgmt
,
334 const size_t min_len
= sizeof(*rxmgmt
) +
335 sizeof(struct ieee80211_hdr_3addr
);
336 const struct ieee80211_hdr_3addr
*frame
= (void *)rxmgmt
->frame_data
;
337 const u16 frame_len
= len
- sizeof(*rxmgmt
);
338 enum nl80211_rxmgmt_flags flags
= 0;
340 if (unlikely(len
< min_len
)) {
341 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
342 vif
->mac
->macid
, vif
->vifid
, len
, min_len
);
346 if (le32_to_cpu(rxmgmt
->flags
) & QLINK_RXMGMT_FLAG_ANSWERED
)
347 flags
|= NL80211_RXMGMT_FLAG_ANSWERED
;
349 pr_debug("%s LEN:%u FC:%.4X SA:%pM\n", vif
->netdev
->name
, frame_len
,
350 le16_to_cpu(frame
->frame_control
), frame
->addr2
);
352 cfg80211_rx_mgmt(&vif
->wdev
, le32_to_cpu(rxmgmt
->freq
), rxmgmt
->sig_dbm
,
353 rxmgmt
->frame_data
, frame_len
, flags
);
359 qtnf_event_handle_scan_results(struct qtnf_vif
*vif
,
360 const struct qlink_event_scan_result
*sr
,
363 struct cfg80211_bss
*bss
;
364 struct ieee80211_channel
*channel
;
365 struct wiphy
*wiphy
= priv_to_wiphy(vif
->mac
);
366 enum cfg80211_bss_frame_type frame_type
= CFG80211_BSS_FTYPE_UNKNOWN
;
371 const struct qlink_tlv_hdr
*tlv
;
372 const u8
*ies
= NULL
;
375 if (len
< sizeof(*sr
)) {
376 pr_err("VIF%u.%u: payload is too short\n", vif
->mac
->macid
,
381 channel
= ieee80211_get_channel(wiphy
, le16_to_cpu(sr
->freq
));
383 pr_err("VIF%u.%u: channel at %u MHz not found\n",
384 vif
->mac
->macid
, vif
->vifid
, le16_to_cpu(sr
->freq
));
388 payload_len
= len
- sizeof(*sr
);
389 tlv
= (struct qlink_tlv_hdr
*)sr
->payload
;
391 while (payload_len
>= sizeof(struct qlink_tlv_hdr
)) {
392 tlv_type
= le16_to_cpu(tlv
->type
);
393 tlv_value_len
= le16_to_cpu(tlv
->len
);
394 tlv_full_len
= tlv_value_len
+ sizeof(struct qlink_tlv_hdr
);
396 if (tlv_full_len
> payload_len
)
399 if (tlv_type
== QTN_TLV_ID_IE_SET
) {
400 const struct qlink_tlv_ie_set
*ie_set
;
403 if (payload_len
< sizeof(*ie_set
))
406 ie_set
= (const struct qlink_tlv_ie_set
*)tlv
;
407 ie_len
= tlv_value_len
-
408 (sizeof(*ie_set
) - sizeof(ie_set
->hdr
));
410 switch (ie_set
->type
) {
411 case QLINK_IE_SET_BEACON_IES
:
412 frame_type
= CFG80211_BSS_FTYPE_BEACON
;
414 case QLINK_IE_SET_PROBE_RESP_IES
:
415 frame_type
= CFG80211_BSS_FTYPE_PRESP
;
418 frame_type
= CFG80211_BSS_FTYPE_UNKNOWN
;
422 ies
= ie_set
->ie_data
;
427 payload_len
-= tlv_full_len
;
428 tlv
= (struct qlink_tlv_hdr
*)(tlv
->val
+ tlv_value_len
);
434 bss
= cfg80211_inform_bss(wiphy
, channel
, frame_type
,
435 sr
->bssid
, get_unaligned_le64(&sr
->tsf
),
436 le16_to_cpu(sr
->capab
),
437 le16_to_cpu(sr
->bintval
), ies
, ies_len
,
438 DBM_TO_MBM(sr
->sig_dbm
), GFP_KERNEL
);
442 cfg80211_put_bss(wiphy
, bss
);
448 qtnf_event_handle_scan_complete(struct qtnf_wmac
*mac
,
449 const struct qlink_event_scan_complete
*status
,
452 if (len
< sizeof(*status
)) {
453 pr_err("MAC%u: payload is too short\n", mac
->macid
);
457 qtnf_scan_done(mac
, le32_to_cpu(status
->flags
) & QLINK_SCAN_ABORTED
);
463 qtnf_event_handle_freq_change(struct qtnf_wmac
*mac
,
464 const struct qlink_event_freq_change
*data
,
467 struct wiphy
*wiphy
= priv_to_wiphy(mac
);
468 struct cfg80211_chan_def chandef
;
469 struct qtnf_vif
*vif
;
472 if (len
< sizeof(*data
)) {
473 pr_err("MAC%u: payload is too short\n", mac
->macid
);
477 if (!wiphy
->registered
)
480 qlink_chandef_q2cfg(wiphy
, &data
->chan
, &chandef
);
482 if (!cfg80211_chandef_valid(&chandef
)) {
483 pr_err("MAC%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n",
484 mac
->macid
, chandef
.chan
->center_freq
,
485 chandef
.center_freq1
, chandef
.center_freq2
,
490 pr_debug("MAC%d: new channel ieee=%u freq1=%u freq2=%u bw=%u\n",
491 mac
->macid
, chandef
.chan
->hw_value
, chandef
.center_freq1
,
492 chandef
.center_freq2
, chandef
.width
);
494 for (i
= 0; i
< QTNF_MAX_INTF
; i
++) {
495 vif
= &mac
->iflist
[i
];
497 if (vif
->wdev
.iftype
== NL80211_IFTYPE_UNSPECIFIED
)
500 if (vif
->wdev
.iftype
== NL80211_IFTYPE_STATION
&&
501 !vif
->wdev
.current_bss
)
507 mutex_lock(&vif
->wdev
.mtx
);
508 cfg80211_ch_switch_notify(vif
->netdev
, &chandef
);
509 mutex_unlock(&vif
->wdev
.mtx
);
515 static int qtnf_event_handle_radar(struct qtnf_vif
*vif
,
516 const struct qlink_event_radar
*ev
,
519 struct wiphy
*wiphy
= priv_to_wiphy(vif
->mac
);
520 struct cfg80211_chan_def chandef
;
522 if (len
< sizeof(*ev
)) {
523 pr_err("MAC%u: payload is too short\n", vif
->mac
->macid
);
527 if (!wiphy
->registered
|| !vif
->netdev
)
530 qlink_chandef_q2cfg(wiphy
, &ev
->chan
, &chandef
);
532 if (!cfg80211_chandef_valid(&chandef
)) {
533 pr_err("MAC%u: bad channel f1=%u f2=%u bw=%u\n",
535 chandef
.center_freq1
, chandef
.center_freq2
,
540 pr_info("%s: radar event=%u f1=%u f2=%u bw=%u\n",
541 vif
->netdev
->name
, ev
->event
,
542 chandef
.center_freq1
, chandef
.center_freq2
,
546 case QLINK_RADAR_DETECTED
:
547 cfg80211_radar_event(wiphy
, &chandef
, GFP_KERNEL
);
549 case QLINK_RADAR_CAC_FINISHED
:
550 if (!vif
->wdev
.cac_started
)
553 cfg80211_cac_event(vif
->netdev
, &chandef
,
554 NL80211_RADAR_CAC_FINISHED
, GFP_KERNEL
);
556 case QLINK_RADAR_CAC_ABORTED
:
557 if (!vif
->wdev
.cac_started
)
560 cfg80211_cac_event(vif
->netdev
, &chandef
,
561 NL80211_RADAR_CAC_ABORTED
, GFP_KERNEL
);
563 case QLINK_RADAR_CAC_STARTED
:
564 if (vif
->wdev
.cac_started
)
567 if (!wiphy_ext_feature_isset(wiphy
,
568 NL80211_EXT_FEATURE_DFS_OFFLOAD
))
571 cfg80211_cac_event(vif
->netdev
, &chandef
,
572 NL80211_RADAR_CAC_STARTED
, GFP_KERNEL
);
575 pr_warn("%s: unhandled radar event %u\n",
576 vif
->netdev
->name
, ev
->event
);
584 qtnf_event_handle_external_auth(struct qtnf_vif
*vif
,
585 const struct qlink_event_external_auth
*ev
,
588 struct cfg80211_external_auth_params auth
= {0};
589 struct wiphy
*wiphy
= priv_to_wiphy(vif
->mac
);
592 if (len
< sizeof(*ev
)) {
593 pr_err("MAC%u: payload is too short\n", vif
->mac
->macid
);
597 if (!wiphy
->registered
|| !vif
->netdev
)
601 memcpy(auth
.ssid
.ssid
, ev
->ssid
, ev
->ssid_len
);
602 auth
.ssid
.ssid_len
= ev
->ssid_len
;
605 auth
.key_mgmt_suite
= le32_to_cpu(ev
->akm_suite
);
606 ether_addr_copy(auth
.bssid
, ev
->bssid
);
607 auth
.action
= ev
->action
;
609 pr_info("%s: external auth bss=%pM action=%u akm=%u\n",
610 vif
->netdev
->name
, auth
.bssid
, auth
.action
,
611 auth
.key_mgmt_suite
);
613 ret
= cfg80211_external_auth_request(vif
->netdev
, &auth
, GFP_KERNEL
);
615 pr_warn("failed to offload external auth request\n");
620 static int qtnf_event_parse(struct qtnf_wmac
*mac
,
621 const struct sk_buff
*event_skb
)
623 const struct qlink_event
*event
;
624 struct qtnf_vif
*vif
= NULL
;
629 event
= (const struct qlink_event
*)event_skb
->data
;
630 event_id
= le16_to_cpu(event
->event_id
);
631 event_len
= le16_to_cpu(event
->mhdr
.len
);
633 if (likely(event
->vifid
< QTNF_MAX_INTF
)) {
634 vif
= &mac
->iflist
[event
->vifid
];
636 pr_err("invalid vif(%u)\n", event
->vifid
);
641 case QLINK_EVENT_STA_ASSOCIATED
:
642 ret
= qtnf_event_handle_sta_assoc(mac
, vif
, (const void *)event
,
645 case QLINK_EVENT_STA_DEAUTH
:
646 ret
= qtnf_event_handle_sta_deauth(mac
, vif
,
650 case QLINK_EVENT_MGMT_RECEIVED
:
651 ret
= qtnf_event_handle_mgmt_received(vif
, (const void *)event
,
654 case QLINK_EVENT_SCAN_RESULTS
:
655 ret
= qtnf_event_handle_scan_results(vif
, (const void *)event
,
658 case QLINK_EVENT_SCAN_COMPLETE
:
659 ret
= qtnf_event_handle_scan_complete(mac
, (const void *)event
,
662 case QLINK_EVENT_BSS_JOIN
:
663 ret
= qtnf_event_handle_bss_join(vif
, (const void *)event
,
666 case QLINK_EVENT_BSS_LEAVE
:
667 ret
= qtnf_event_handle_bss_leave(vif
, (const void *)event
,
670 case QLINK_EVENT_FREQ_CHANGE
:
671 ret
= qtnf_event_handle_freq_change(mac
, (const void *)event
,
674 case QLINK_EVENT_RADAR
:
675 ret
= qtnf_event_handle_radar(vif
, (const void *)event
,
678 case QLINK_EVENT_EXTERNAL_AUTH
:
679 ret
= qtnf_event_handle_external_auth(vif
, (const void *)event
,
683 pr_warn("unknown event type: %x\n", event_id
);
690 static int qtnf_event_process_skb(struct qtnf_bus
*bus
,
691 const struct sk_buff
*skb
)
693 const struct qlink_event
*event
;
694 struct qtnf_wmac
*mac
;
697 if (unlikely(!skb
|| skb
->len
< sizeof(*event
))) {
698 pr_err("invalid event buffer\n");
702 event
= (struct qlink_event
*)skb
->data
;
704 mac
= qtnf_core_get_mac(bus
, event
->macid
);
706 pr_debug("new event id:%x len:%u mac:%u vif:%u\n",
707 le16_to_cpu(event
->event_id
), le16_to_cpu(event
->mhdr
.len
),
708 event
->macid
, event
->vifid
);
714 res
= qtnf_event_parse(mac
, skb
);
720 void qtnf_event_work_handler(struct work_struct
*work
)
722 struct qtnf_bus
*bus
= container_of(work
, struct qtnf_bus
, event_work
);
723 struct sk_buff_head
*event_queue
= &bus
->trans
.event_queue
;
724 struct sk_buff
*current_event_skb
= skb_dequeue(event_queue
);
726 while (current_event_skb
) {
727 qtnf_event_process_skb(bus
, current_event_skb
);
728 dev_kfree_skb_any(current_event_skb
);
729 current_event_skb
= skb_dequeue(event_queue
);