]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/net/wireless/quantenna/qtnfmac/event.c
wil6210: rate limit wil_rx_refill error
[linux.git] / drivers / net / wireless / quantenna / qtnfmac / event.c
1 /*
2  * Copyright (c) 2015-2016 Quantenna Communications, Inc.
3  * All rights reserved.
4  *
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.
9  *
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.
14  *
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/slab.h>
20
21 #include "cfg80211.h"
22 #include "core.h"
23 #include "qlink.h"
24 #include "bus.h"
25 #include "trans.h"
26 #include "util.h"
27 #include "event.h"
28 #include "qlink_util.h"
29
30 static int
31 qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif,
32                             const struct qlink_event_sta_assoc *sta_assoc,
33                             u16 len)
34 {
35         const u8 *sta_addr;
36         u16 frame_control;
37         struct station_info sinfo = { 0 };
38         size_t payload_len;
39         u16 tlv_type;
40         u16 tlv_value_len;
41         size_t tlv_full_len;
42         const struct qlink_tlv_hdr *tlv;
43
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));
47                 return -EINVAL;
48         }
49
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);
53                 return -EPROTO;
54         }
55
56         sta_addr = sta_assoc->sta_addr;
57         frame_control = le16_to_cpu(sta_assoc->frame_control);
58
59         pr_debug("VIF%u.%u: MAC:%pM FC:%x\n", mac->macid, vif->vifid, sta_addr,
60                  frame_control);
61
62         qtnf_sta_list_add(vif, sta_addr);
63
64         sinfo.assoc_req_ies = NULL;
65         sinfo.assoc_req_ies_len = 0;
66         sinfo.generation = vif->generation;
67
68         payload_len = len - sizeof(*sta_assoc);
69         tlv = (const struct qlink_tlv_hdr *)sta_assoc->ies;
70
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);
75
76                 if (tlv_full_len > payload_len)
77                         return -EINVAL;
78
79                 if (tlv_type == QTN_TLV_ID_IE_SET) {
80                         const struct qlink_tlv_ie_set *ie_set;
81                         unsigned int ie_len;
82
83                         if (payload_len < sizeof(*ie_set))
84                                 return -EINVAL;
85
86                         ie_set = (const struct qlink_tlv_ie_set *)tlv;
87                         ie_len = tlv_value_len -
88                                 (sizeof(*ie_set) - sizeof(ie_set->hdr));
89
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;
93                         }
94                 }
95
96                 payload_len -= tlv_full_len;
97                 tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
98         }
99
100         if (payload_len)
101                 return -EINVAL;
102
103         cfg80211_new_sta(vif->netdev, sta_assoc->sta_addr, &sinfo,
104                          GFP_KERNEL);
105
106         return 0;
107 }
108
109 static int
110 qtnf_event_handle_sta_deauth(struct qtnf_wmac *mac, struct qtnf_vif *vif,
111                              const struct qlink_event_sta_deauth *sta_deauth,
112                              u16 len)
113 {
114         const u8 *sta_addr;
115         u16 reason;
116
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));
121                 return -EINVAL;
122         }
123
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);
127                 return -EPROTO;
128         }
129
130         sta_addr = sta_deauth->sta_addr;
131         reason = le16_to_cpu(sta_deauth->reason);
132
133         pr_debug("VIF%u.%u: MAC:%pM reason:%x\n", mac->macid, vif->vifid,
134                  sta_addr, reason);
135
136         if (qtnf_sta_list_del(vif, sta_addr))
137                 cfg80211_del_sta(vif->netdev, sta_deauth->sta_addr,
138                                  GFP_KERNEL);
139
140         return 0;
141 }
142
143 static int
144 qtnf_event_handle_bss_join(struct qtnf_vif *vif,
145                            const struct qlink_event_bss_join *join_info,
146                            u16 len)
147 {
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));
152                 return -EINVAL;
153         }
154
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);
158                 return -EPROTO;
159         }
160
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);
164                 return -EPROTO;
165         }
166
167         pr_debug("VIF%u.%u: BSSID:%pM\n", vif->mac->macid, vif->vifid,
168                  join_info->bssid);
169
170         cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL,
171                                 0, le16_to_cpu(join_info->status), GFP_KERNEL);
172
173         if (le16_to_cpu(join_info->status) == WLAN_STATUS_SUCCESS) {
174                 vif->sta_state = QTNF_STA_CONNECTED;
175                 netif_carrier_on(vif->netdev);
176         } else {
177                 vif->sta_state = QTNF_STA_DISCONNECTED;
178         }
179
180         return 0;
181 }
182
183 static int
184 qtnf_event_handle_bss_leave(struct qtnf_vif *vif,
185                             const struct qlink_event_bss_leave *leave_info,
186                             u16 len)
187 {
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));
192                 return -EINVAL;
193         }
194
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);
198                 return -EPROTO;
199         }
200
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);
204                 return -EPROTO;
205         }
206
207         pr_debug("VIF%u.%u: disconnected\n", vif->mac->macid, vif->vifid);
208
209         cfg80211_disconnected(vif->netdev, le16_to_cpu(leave_info->reason),
210                               NULL, 0, 0, GFP_KERNEL);
211
212         vif->sta_state = QTNF_STA_DISCONNECTED;
213         netif_carrier_off(vif->netdev);
214
215         return 0;
216 }
217
218 static int
219 qtnf_event_handle_mgmt_received(struct qtnf_vif *vif,
220                                 const struct qlink_event_rxmgmt *rxmgmt,
221                                 u16 len)
222 {
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;
228
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);
232                 return -EINVAL;
233         }
234
235         if (le32_to_cpu(rxmgmt->flags) & QLINK_RXMGMT_FLAG_ANSWERED)
236                 flags |= NL80211_RXMGMT_FLAG_ANSWERED;
237
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);
240
241         cfg80211_rx_mgmt(&vif->wdev, le32_to_cpu(rxmgmt->freq), rxmgmt->sig_dbm,
242                          rxmgmt->frame_data, frame_len, flags);
243
244         return 0;
245 }
246
247 static int
248 qtnf_event_handle_scan_results(struct qtnf_vif *vif,
249                                const struct qlink_event_scan_result *sr,
250                                u16 len)
251 {
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;
256         size_t payload_len;
257         u16 tlv_type;
258         u16 tlv_value_len;
259         size_t tlv_full_len;
260         const struct qlink_tlv_hdr *tlv;
261         const u8 *ies = NULL;
262         size_t ies_len = 0;
263
264         if (len < sizeof(*sr)) {
265                 pr_err("VIF%u.%u: payload is too short\n", vif->mac->macid,
266                        vif->vifid);
267                 return -EINVAL;
268         }
269
270         channel = ieee80211_get_channel(wiphy, le16_to_cpu(sr->freq));
271         if (!channel) {
272                 pr_err("VIF%u.%u: channel at %u MHz not found\n",
273                        vif->mac->macid, vif->vifid, le16_to_cpu(sr->freq));
274                 return -EINVAL;
275         }
276
277         payload_len = len - sizeof(*sr);
278         tlv = (struct qlink_tlv_hdr *)sr->payload;
279
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);
284
285                 if (tlv_full_len > payload_len)
286                         return -EINVAL;
287
288                 if (tlv_type == QTN_TLV_ID_IE_SET) {
289                         const struct qlink_tlv_ie_set *ie_set;
290                         unsigned int ie_len;
291
292                         if (payload_len < sizeof(*ie_set))
293                                 return -EINVAL;
294
295                         ie_set = (const struct qlink_tlv_ie_set *)tlv;
296                         ie_len = tlv_value_len -
297                                 (sizeof(*ie_set) - sizeof(ie_set->hdr));
298
299                         switch (ie_set->type) {
300                         case QLINK_IE_SET_BEACON_IES:
301                                 frame_type = CFG80211_BSS_FTYPE_BEACON;
302                                 break;
303                         case QLINK_IE_SET_PROBE_RESP_IES:
304                                 frame_type = CFG80211_BSS_FTYPE_PRESP;
305                                 break;
306                         default:
307                                 frame_type = CFG80211_BSS_FTYPE_UNKNOWN;
308                         }
309
310                         if (ie_len) {
311                                 ies = ie_set->ie_data;
312                                 ies_len = ie_len;
313                         }
314                 }
315
316                 payload_len -= tlv_full_len;
317                 tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len);
318         }
319
320         if (payload_len)
321                 return -EINVAL;
322
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);
328         if (!bss)
329                 return -ENOMEM;
330
331         cfg80211_put_bss(wiphy, bss);
332
333         return 0;
334 }
335
336 static int
337 qtnf_event_handle_scan_complete(struct qtnf_wmac *mac,
338                                 const struct qlink_event_scan_complete *status,
339                                 u16 len)
340 {
341         if (len < sizeof(*status)) {
342                 pr_err("MAC%u: payload is too short\n", mac->macid);
343                 return -EINVAL;
344         }
345
346         qtnf_scan_done(mac, le32_to_cpu(status->flags) & QLINK_SCAN_ABORTED);
347
348         return 0;
349 }
350
351 static int
352 qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
353                               const struct qlink_event_freq_change *data,
354                               u16 len)
355 {
356         struct wiphy *wiphy = priv_to_wiphy(mac);
357         struct cfg80211_chan_def chandef;
358         struct qtnf_vif *vif;
359         int i;
360
361         if (len < sizeof(*data)) {
362                 pr_err("MAC%u: payload is too short\n", mac->macid);
363                 return -EINVAL;
364         }
365
366         if (!wiphy->registered)
367                 return 0;
368
369         qlink_chandef_q2cfg(wiphy, &data->chan, &chandef);
370
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,
375                        chandef.width);
376                 return -EINVAL;
377         }
378
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);
382
383         for (i = 0; i < QTNF_MAX_INTF; i++) {
384                 vif = &mac->iflist[i];
385                 if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)
386                         continue;
387
388                 if (vif->netdev) {
389                         mutex_lock(&vif->wdev.mtx);
390                         cfg80211_ch_switch_notify(vif->netdev, &chandef);
391                         mutex_unlock(&vif->wdev.mtx);
392                 }
393         }
394
395         return 0;
396 }
397
398 static int qtnf_event_handle_radar(struct qtnf_vif *vif,
399                                    const struct qlink_event_radar *ev,
400                                    u16 len)
401 {
402         struct wiphy *wiphy = priv_to_wiphy(vif->mac);
403         struct cfg80211_chan_def chandef;
404
405         if (len < sizeof(*ev)) {
406                 pr_err("MAC%u: payload is too short\n", vif->mac->macid);
407                 return -EINVAL;
408         }
409
410         if (!wiphy->registered || !vif->netdev)
411                 return 0;
412
413         qlink_chandef_q2cfg(wiphy, &ev->chan, &chandef);
414
415         if (!cfg80211_chandef_valid(&chandef)) {
416                 pr_err("MAC%u: bad channel f1=%u f2=%u bw=%u\n",
417                        vif->mac->macid,
418                        chandef.center_freq1, chandef.center_freq2,
419                        chandef.width);
420                 return -EINVAL;
421         }
422
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,
426                 chandef.width);
427
428         switch (ev->event) {
429         case QLINK_RADAR_DETECTED:
430                 cfg80211_radar_event(wiphy, &chandef, GFP_KERNEL);
431                 break;
432         case QLINK_RADAR_CAC_FINISHED:
433                 if (!vif->wdev.cac_started)
434                         break;
435
436                 cfg80211_cac_event(vif->netdev, &chandef,
437                                    NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
438                 break;
439         case QLINK_RADAR_CAC_ABORTED:
440                 if (!vif->wdev.cac_started)
441                         break;
442
443                 cfg80211_cac_event(vif->netdev, &chandef,
444                                    NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
445                 break;
446         case QLINK_RADAR_CAC_STARTED:
447                 if (vif->wdev.cac_started)
448                         break;
449
450                 if (!wiphy_ext_feature_isset(wiphy,
451                                              NL80211_EXT_FEATURE_DFS_OFFLOAD))
452                         break;
453
454                 cfg80211_cac_event(vif->netdev, &chandef,
455                                    NL80211_RADAR_CAC_STARTED, GFP_KERNEL);
456                 break;
457         default:
458                 pr_warn("%s: unhandled radar event %u\n",
459                         vif->netdev->name, ev->event);
460                 break;
461         }
462
463         return 0;
464 }
465
466 static int qtnf_event_parse(struct qtnf_wmac *mac,
467                             const struct sk_buff *event_skb)
468 {
469         const struct qlink_event *event;
470         struct qtnf_vif *vif = NULL;
471         int ret = -1;
472         u16 event_id;
473         u16 event_len;
474
475         event = (const struct qlink_event *)event_skb->data;
476         event_id = le16_to_cpu(event->event_id);
477         event_len = le16_to_cpu(event->mhdr.len);
478
479         if (likely(event->vifid < QTNF_MAX_INTF)) {
480                 vif = &mac->iflist[event->vifid];
481         } else {
482                 pr_err("invalid vif(%u)\n", event->vifid);
483                 return -EINVAL;
484         }
485
486         switch (event_id) {
487         case QLINK_EVENT_STA_ASSOCIATED:
488                 ret = qtnf_event_handle_sta_assoc(mac, vif, (const void *)event,
489                                                   event_len);
490                 break;
491         case QLINK_EVENT_STA_DEAUTH:
492                 ret = qtnf_event_handle_sta_deauth(mac, vif,
493                                                    (const void *)event,
494                                                    event_len);
495                 break;
496         case QLINK_EVENT_MGMT_RECEIVED:
497                 ret = qtnf_event_handle_mgmt_received(vif, (const void *)event,
498                                                       event_len);
499                 break;
500         case QLINK_EVENT_SCAN_RESULTS:
501                 ret = qtnf_event_handle_scan_results(vif, (const void *)event,
502                                                      event_len);
503                 break;
504         case QLINK_EVENT_SCAN_COMPLETE:
505                 ret = qtnf_event_handle_scan_complete(mac, (const void *)event,
506                                                       event_len);
507                 break;
508         case QLINK_EVENT_BSS_JOIN:
509                 ret = qtnf_event_handle_bss_join(vif, (const void *)event,
510                                                  event_len);
511                 break;
512         case QLINK_EVENT_BSS_LEAVE:
513                 ret = qtnf_event_handle_bss_leave(vif, (const void *)event,
514                                                   event_len);
515                 break;
516         case QLINK_EVENT_FREQ_CHANGE:
517                 ret = qtnf_event_handle_freq_change(mac, (const void *)event,
518                                                     event_len);
519                 break;
520         case QLINK_EVENT_RADAR:
521                 ret = qtnf_event_handle_radar(vif, (const void *)event,
522                                               event_len);
523                 break;
524         default:
525                 pr_warn("unknown event type: %x\n", event_id);
526                 break;
527         }
528
529         return ret;
530 }
531
532 static int qtnf_event_process_skb(struct qtnf_bus *bus,
533                                   const struct sk_buff *skb)
534 {
535         const struct qlink_event *event;
536         struct qtnf_wmac *mac;
537         int res;
538
539         if (unlikely(!skb || skb->len < sizeof(*event))) {
540                 pr_err("invalid event buffer\n");
541                 return -EINVAL;
542         }
543
544         event = (struct qlink_event *)skb->data;
545
546         mac = qtnf_core_get_mac(bus, event->macid);
547
548         pr_debug("new event id:%x len:%u mac:%u vif:%u\n",
549                  le16_to_cpu(event->event_id), le16_to_cpu(event->mhdr.len),
550                  event->macid, event->vifid);
551
552         if (unlikely(!mac))
553                 return -ENXIO;
554
555         rtnl_lock();
556         res = qtnf_event_parse(mac, skb);
557         rtnl_unlock();
558
559         return res;
560 }
561
562 void qtnf_event_work_handler(struct work_struct *work)
563 {
564         struct qtnf_bus *bus = container_of(work, struct qtnf_bus, event_work);
565         struct sk_buff_head *event_queue = &bus->trans.event_queue;
566         struct sk_buff *current_event_skb = skb_dequeue(event_queue);
567
568         while (current_event_skb) {
569                 qtnf_event_process_skb(bus, current_event_skb);
570                 dev_kfree_skb_any(current_event_skb);
571                 current_event_skb = skb_dequeue(event_queue);
572         }
573 }