2 * Copyright (c) 2015-2016 Quantenna Communications, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/slab.h>
28 #include "qlink_util.h"
31 qtnf_event_handle_sta_assoc(struct qtnf_wmac
*mac
, struct qtnf_vif
*vif
,
32 const struct qlink_event_sta_assoc
*sta_assoc
,
37 struct station_info sinfo
= { 0 };
42 const struct qlink_tlv_hdr
*tlv
;
44 if (unlikely(len
< sizeof(*sta_assoc
))) {
45 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
46 mac
->macid
, vif
->vifid
, len
, sizeof(*sta_assoc
));
50 if (vif
->wdev
.iftype
!= NL80211_IFTYPE_AP
) {
51 pr_err("VIF%u.%u: STA_ASSOC event when not in AP mode\n",
52 mac
->macid
, vif
->vifid
);
56 sta_addr
= sta_assoc
->sta_addr
;
57 frame_control
= le16_to_cpu(sta_assoc
->frame_control
);
59 pr_debug("VIF%u.%u: MAC:%pM FC:%x\n", mac
->macid
, vif
->vifid
, sta_addr
,
62 qtnf_sta_list_add(vif
, sta_addr
);
64 sinfo
.assoc_req_ies
= NULL
;
65 sinfo
.assoc_req_ies_len
= 0;
66 sinfo
.generation
= vif
->generation
;
68 payload_len
= len
- sizeof(*sta_assoc
);
69 tlv
= (const struct qlink_tlv_hdr
*)sta_assoc
->ies
;
71 while (payload_len
>= sizeof(*tlv
)) {
72 tlv_type
= le16_to_cpu(tlv
->type
);
73 tlv_value_len
= le16_to_cpu(tlv
->len
);
74 tlv_full_len
= tlv_value_len
+ sizeof(struct qlink_tlv_hdr
);
76 if (tlv_full_len
> payload_len
)
79 if (tlv_type
== QTN_TLV_ID_IE_SET
) {
80 const struct qlink_tlv_ie_set
*ie_set
;
83 if (payload_len
< sizeof(*ie_set
))
86 ie_set
= (const struct qlink_tlv_ie_set
*)tlv
;
87 ie_len
= tlv_value_len
-
88 (sizeof(*ie_set
) - sizeof(ie_set
->hdr
));
90 if (ie_set
->type
== QLINK_IE_SET_ASSOC_REQ
&& ie_len
) {
91 sinfo
.assoc_req_ies
= ie_set
->ie_data
;
92 sinfo
.assoc_req_ies_len
= ie_len
;
96 payload_len
-= tlv_full_len
;
97 tlv
= (struct qlink_tlv_hdr
*)(tlv
->val
+ tlv_value_len
);
103 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 if (unlikely(len
< sizeof(*join_info
))) {
149 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
150 vif
->mac
->macid
, vif
->vifid
, len
,
151 sizeof(struct qlink_event_bss_join
));
155 if (vif
->wdev
.iftype
!= NL80211_IFTYPE_STATION
) {
156 pr_err("VIF%u.%u: BSS_JOIN event when not in STA mode\n",
157 vif
->mac
->macid
, vif
->vifid
);
161 if (vif
->sta_state
!= QTNF_STA_CONNECTING
) {
162 pr_err("VIF%u.%u: BSS_JOIN event when STA is not connecting\n",
163 vif
->mac
->macid
, vif
->vifid
);
167 pr_debug("VIF%u.%u: BSSID:%pM\n", vif
->mac
->macid
, vif
->vifid
,
170 cfg80211_connect_result(vif
->netdev
, join_info
->bssid
, NULL
, 0, NULL
,
171 0, le16_to_cpu(join_info
->status
), GFP_KERNEL
);
173 if (le16_to_cpu(join_info
->status
) == WLAN_STATUS_SUCCESS
) {
174 vif
->sta_state
= QTNF_STA_CONNECTED
;
175 netif_carrier_on(vif
->netdev
);
177 vif
->sta_state
= QTNF_STA_DISCONNECTED
;
184 qtnf_event_handle_bss_leave(struct qtnf_vif
*vif
,
185 const struct qlink_event_bss_leave
*leave_info
,
188 if (unlikely(len
< sizeof(*leave_info
))) {
189 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
190 vif
->mac
->macid
, vif
->vifid
, len
,
191 sizeof(struct qlink_event_bss_leave
));
195 if (vif
->wdev
.iftype
!= NL80211_IFTYPE_STATION
) {
196 pr_err("VIF%u.%u: BSS_LEAVE event when not in STA mode\n",
197 vif
->mac
->macid
, vif
->vifid
);
201 if (vif
->sta_state
!= QTNF_STA_CONNECTED
) {
202 pr_err("VIF%u.%u: BSS_LEAVE event when STA is not connected\n",
203 vif
->mac
->macid
, vif
->vifid
);
207 pr_debug("VIF%u.%u: disconnected\n", vif
->mac
->macid
, vif
->vifid
);
209 cfg80211_disconnected(vif
->netdev
, le16_to_cpu(leave_info
->reason
),
210 NULL
, 0, 0, GFP_KERNEL
);
212 vif
->sta_state
= QTNF_STA_DISCONNECTED
;
213 netif_carrier_off(vif
->netdev
);
219 qtnf_event_handle_mgmt_received(struct qtnf_vif
*vif
,
220 const struct qlink_event_rxmgmt
*rxmgmt
,
223 const size_t min_len
= sizeof(*rxmgmt
) +
224 sizeof(struct ieee80211_hdr_3addr
);
225 const struct ieee80211_hdr_3addr
*frame
= (void *)rxmgmt
->frame_data
;
226 const u16 frame_len
= len
- sizeof(*rxmgmt
);
227 enum nl80211_rxmgmt_flags flags
= 0;
229 if (unlikely(len
< min_len
)) {
230 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
231 vif
->mac
->macid
, vif
->vifid
, len
, min_len
);
235 if (le32_to_cpu(rxmgmt
->flags
) & QLINK_RXMGMT_FLAG_ANSWERED
)
236 flags
|= NL80211_RXMGMT_FLAG_ANSWERED
;
238 pr_debug("%s LEN:%u FC:%.4X SA:%pM\n", vif
->netdev
->name
, frame_len
,
239 le16_to_cpu(frame
->frame_control
), frame
->addr2
);
241 cfg80211_rx_mgmt(&vif
->wdev
, le32_to_cpu(rxmgmt
->freq
), rxmgmt
->sig_dbm
,
242 rxmgmt
->frame_data
, frame_len
, flags
);
248 qtnf_event_handle_scan_results(struct qtnf_vif
*vif
,
249 const struct qlink_event_scan_result
*sr
,
252 struct cfg80211_bss
*bss
;
253 struct ieee80211_channel
*channel
;
254 struct wiphy
*wiphy
= priv_to_wiphy(vif
->mac
);
255 enum cfg80211_bss_frame_type frame_type
= CFG80211_BSS_FTYPE_UNKNOWN
;
260 const struct qlink_tlv_hdr
*tlv
;
261 const u8
*ies
= NULL
;
264 if (len
< sizeof(*sr
)) {
265 pr_err("VIF%u.%u: payload is too short\n", vif
->mac
->macid
,
270 channel
= ieee80211_get_channel(wiphy
, le16_to_cpu(sr
->freq
));
272 pr_err("VIF%u.%u: channel at %u MHz not found\n",
273 vif
->mac
->macid
, vif
->vifid
, le16_to_cpu(sr
->freq
));
277 payload_len
= len
- sizeof(*sr
);
278 tlv
= (struct qlink_tlv_hdr
*)sr
->payload
;
280 while (payload_len
>= sizeof(struct qlink_tlv_hdr
)) {
281 tlv_type
= le16_to_cpu(tlv
->type
);
282 tlv_value_len
= le16_to_cpu(tlv
->len
);
283 tlv_full_len
= tlv_value_len
+ sizeof(struct qlink_tlv_hdr
);
285 if (tlv_full_len
> payload_len
)
288 if (tlv_type
== QTN_TLV_ID_IE_SET
) {
289 const struct qlink_tlv_ie_set
*ie_set
;
292 if (payload_len
< sizeof(*ie_set
))
295 ie_set
= (const struct qlink_tlv_ie_set
*)tlv
;
296 ie_len
= tlv_value_len
-
297 (sizeof(*ie_set
) - sizeof(ie_set
->hdr
));
299 switch (ie_set
->type
) {
300 case QLINK_IE_SET_BEACON_IES
:
301 frame_type
= CFG80211_BSS_FTYPE_BEACON
;
303 case QLINK_IE_SET_PROBE_RESP_IES
:
304 frame_type
= CFG80211_BSS_FTYPE_PRESP
;
307 frame_type
= CFG80211_BSS_FTYPE_UNKNOWN
;
311 ies
= ie_set
->ie_data
;
316 payload_len
-= tlv_full_len
;
317 tlv
= (struct qlink_tlv_hdr
*)(tlv
->val
+ tlv_value_len
);
323 bss
= cfg80211_inform_bss(wiphy
, channel
, frame_type
,
324 sr
->bssid
, get_unaligned_le64(&sr
->tsf
),
325 le16_to_cpu(sr
->capab
),
326 le16_to_cpu(sr
->bintval
), ies
, ies_len
,
327 DBM_TO_MBM(sr
->sig_dbm
), GFP_KERNEL
);
331 cfg80211_put_bss(wiphy
, bss
);
337 qtnf_event_handle_scan_complete(struct qtnf_wmac
*mac
,
338 const struct qlink_event_scan_complete
*status
,
341 if (len
< sizeof(*status
)) {
342 pr_err("MAC%u: payload is too short\n", mac
->macid
);
346 qtnf_scan_done(mac
, le32_to_cpu(status
->flags
) & QLINK_SCAN_ABORTED
);
352 qtnf_event_handle_freq_change(struct qtnf_wmac
*mac
,
353 const struct qlink_event_freq_change
*data
,
356 struct wiphy
*wiphy
= priv_to_wiphy(mac
);
357 struct cfg80211_chan_def chandef
;
358 struct qtnf_vif
*vif
;
361 if (len
< sizeof(*data
)) {
362 pr_err("MAC%u: payload is too short\n", mac
->macid
);
366 if (!wiphy
->registered
)
369 qlink_chandef_q2cfg(wiphy
, &data
->chan
, &chandef
);
371 if (!cfg80211_chandef_valid(&chandef
)) {
372 pr_err("MAC%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n",
373 mac
->macid
, chandef
.chan
->center_freq
,
374 chandef
.center_freq1
, chandef
.center_freq2
,
379 pr_debug("MAC%d: new channel ieee=%u freq1=%u freq2=%u bw=%u\n",
380 mac
->macid
, chandef
.chan
->hw_value
, chandef
.center_freq1
,
381 chandef
.center_freq2
, chandef
.width
);
383 for (i
= 0; i
< QTNF_MAX_INTF
; i
++) {
384 vif
= &mac
->iflist
[i
];
385 if (vif
->wdev
.iftype
== NL80211_IFTYPE_UNSPECIFIED
)
389 mutex_lock(&vif
->wdev
.mtx
);
390 cfg80211_ch_switch_notify(vif
->netdev
, &chandef
);
391 mutex_unlock(&vif
->wdev
.mtx
);
398 static int qtnf_event_handle_radar(struct qtnf_vif
*vif
,
399 const struct qlink_event_radar
*ev
,
402 struct wiphy
*wiphy
= priv_to_wiphy(vif
->mac
);
403 struct cfg80211_chan_def chandef
;
405 if (len
< sizeof(*ev
)) {
406 pr_err("MAC%u: payload is too short\n", vif
->mac
->macid
);
410 if (!wiphy
->registered
|| !vif
->netdev
)
413 qlink_chandef_q2cfg(wiphy
, &ev
->chan
, &chandef
);
415 if (!cfg80211_chandef_valid(&chandef
)) {
416 pr_err("MAC%u: bad channel f1=%u f2=%u bw=%u\n",
418 chandef
.center_freq1
, chandef
.center_freq2
,
423 pr_info("%s: radar event=%u f1=%u f2=%u bw=%u\n",
424 vif
->netdev
->name
, ev
->event
,
425 chandef
.center_freq1
, chandef
.center_freq2
,
429 case QLINK_RADAR_DETECTED
:
430 cfg80211_radar_event(wiphy
, &chandef
, GFP_KERNEL
);
432 case QLINK_RADAR_CAC_FINISHED
:
433 if (!vif
->wdev
.cac_started
)
436 cfg80211_cac_event(vif
->netdev
, &chandef
,
437 NL80211_RADAR_CAC_FINISHED
, GFP_KERNEL
);
439 case QLINK_RADAR_CAC_ABORTED
:
440 if (!vif
->wdev
.cac_started
)
443 cfg80211_cac_event(vif
->netdev
, &chandef
,
444 NL80211_RADAR_CAC_ABORTED
, GFP_KERNEL
);
447 pr_warn("%s: unhandled radar event %u\n",
448 vif
->netdev
->name
, ev
->event
);
455 static int qtnf_event_parse(struct qtnf_wmac
*mac
,
456 const struct sk_buff
*event_skb
)
458 const struct qlink_event
*event
;
459 struct qtnf_vif
*vif
= NULL
;
464 event
= (const struct qlink_event
*)event_skb
->data
;
465 event_id
= le16_to_cpu(event
->event_id
);
466 event_len
= le16_to_cpu(event
->mhdr
.len
);
468 if (likely(event
->vifid
< QTNF_MAX_INTF
)) {
469 vif
= &mac
->iflist
[event
->vifid
];
471 pr_err("invalid vif(%u)\n", event
->vifid
);
476 case QLINK_EVENT_STA_ASSOCIATED
:
477 ret
= qtnf_event_handle_sta_assoc(mac
, vif
, (const void *)event
,
480 case QLINK_EVENT_STA_DEAUTH
:
481 ret
= qtnf_event_handle_sta_deauth(mac
, vif
,
485 case QLINK_EVENT_MGMT_RECEIVED
:
486 ret
= qtnf_event_handle_mgmt_received(vif
, (const void *)event
,
489 case QLINK_EVENT_SCAN_RESULTS
:
490 ret
= qtnf_event_handle_scan_results(vif
, (const void *)event
,
493 case QLINK_EVENT_SCAN_COMPLETE
:
494 ret
= qtnf_event_handle_scan_complete(mac
, (const void *)event
,
497 case QLINK_EVENT_BSS_JOIN
:
498 ret
= qtnf_event_handle_bss_join(vif
, (const void *)event
,
501 case QLINK_EVENT_BSS_LEAVE
:
502 ret
= qtnf_event_handle_bss_leave(vif
, (const void *)event
,
505 case QLINK_EVENT_FREQ_CHANGE
:
506 ret
= qtnf_event_handle_freq_change(mac
, (const void *)event
,
509 case QLINK_EVENT_RADAR
:
510 ret
= qtnf_event_handle_radar(vif
, (const void *)event
,
514 pr_warn("unknown event type: %x\n", event_id
);
521 static int qtnf_event_process_skb(struct qtnf_bus
*bus
,
522 const struct sk_buff
*skb
)
524 const struct qlink_event
*event
;
525 struct qtnf_wmac
*mac
;
528 if (unlikely(!skb
|| skb
->len
< sizeof(*event
))) {
529 pr_err("invalid event buffer\n");
533 event
= (struct qlink_event
*)skb
->data
;
535 mac
= qtnf_core_get_mac(bus
, event
->macid
);
537 pr_debug("new event id:%x len:%u mac:%u vif:%u\n",
538 le16_to_cpu(event
->event_id
), le16_to_cpu(event
->mhdr
.len
),
539 event
->macid
, event
->vifid
);
545 res
= qtnf_event_parse(mac
, skb
);
546 qtnf_bus_unlock(bus
);
551 void qtnf_event_work_handler(struct work_struct
*work
)
553 struct qtnf_bus
*bus
= container_of(work
, struct qtnf_bus
, event_work
);
554 struct sk_buff_head
*event_queue
= &bus
->trans
.event_queue
;
555 struct sk_buff
*current_event_skb
= skb_dequeue(event_queue
);
557 while (current_event_skb
) {
558 qtnf_event_process_skb(bus
, current_event_skb
);
559 dev_kfree_skb_any(current_event_skb
);
560 current_event_skb
= skb_dequeue(event_queue
);