net:wireless:Support eswin usb wifi ECR6600U
[platform/kernel/linux-starfive.git] / drivers / net / wireless / eswin / fullmac / ecrnx_main.c
1 /**
2  ******************************************************************************
3  *
4  * @file ecrnx_main.c
5  *
6  * @brief Entry point of the ECRNX driver
7  *
8  * Copyright (C) ESWIN 2015-2020
9  *
10  ******************************************************************************
11  */
12
13 #include <linux/module.h>
14 #include <linux/pci.h>
15 #include <linux/inetdevice.h>
16 #include <net/cfg80211.h>
17 #include <net/ip.h>
18 #include <linux/etherdevice.h>
19
20 #include "ecrnx_defs.h"
21 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
22 #include <linux/if_arp.h>
23 #include <linux/ieee80211.h>
24 #endif
25 #include "ecrnx_msg_tx.h"
26 #include "ecrnx_tx.h"
27 #include "reg_access.h"
28 #include "hal_desc.h"
29 #include "ecrnx_debugfs.h"
30 #include "ecrnx_cfgfile.h"
31 #include "ecrnx_radar.h"
32 #include "ecrnx_version.h"
33 #ifdef CONFIG_ECRNX_BFMER
34 #include "ecrnx_bfmer.h"
35 #endif //(CONFIG_ECRNX_BFMER)
36 #include "ecrnx_tdls.h"
37 #include "ecrnx_events.h"
38 #include "ecrnx_compat.h"
39 #include "ecrnx_rx.h"
40
41 #include "ecrnx_p2p.h"
42 #include "ecrnx_debugfs_custom.h"
43 #include "ecrnx_calibration_data.h"
44 #include "eswin_utils.h"
45 #include "ecrnx_debugfs_func.h"
46
47
48 static struct ieee80211_rate ecrnx_ratetable[] = {
49     RATE(10,  0x00, 0),
50     RATE(20,  0x01, IEEE80211_RATE_SHORT_PREAMBLE),
51     RATE(55,  0x02, IEEE80211_RATE_SHORT_PREAMBLE),
52     RATE(110, 0x03, IEEE80211_RATE_SHORT_PREAMBLE),
53     RATE(60,  0x04, 0),
54     RATE(90,  0x05, 0),
55     RATE(120, 0x06, 0),
56     RATE(180, 0x07, 0),
57     RATE(240, 0x08, 0),
58     RATE(360, 0x09, 0),
59     RATE(480, 0x0A, 0),
60     RATE(540, 0x0B, 0),
61 };
62
63 /* The channels indexes here are not used anymore */
64 static struct ieee80211_channel ecrnx_2ghz_channels[] = {
65     CHAN(2412),
66     CHAN(2417),
67     CHAN(2422),
68     CHAN(2427),
69     CHAN(2432),
70     CHAN(2437),
71     CHAN(2442),
72     CHAN(2447),
73     CHAN(2452),
74     CHAN(2457),
75     CHAN(2462),
76     CHAN(2467),
77     CHAN(2472),
78     CHAN(2484),
79     // Extra channels defined only to be used for PHY measures.
80     // Enabled only if custregd and custchan parameters are set
81     CHAN(2390),
82     CHAN(2400),
83     CHAN(2410),
84     CHAN(2420),
85     CHAN(2430),
86     CHAN(2440),
87     CHAN(2450),
88     CHAN(2460),
89     CHAN(2470),
90     CHAN(2480),
91     CHAN(2490),
92     CHAN(2500),
93     CHAN(2510),
94 };
95
96 #ifdef CONFIG_ECRNX_5G
97 static struct ieee80211_channel ecrnx_5ghz_channels[] = {
98     CHAN(5180),             // 36 -   20MHz
99     CHAN(5200),             // 40 -   20MHz
100     CHAN(5220),             // 44 -   20MHz
101     CHAN(5240),             // 48 -   20MHz
102     CHAN(5260),             // 52 -   20MHz
103     CHAN(5280),             // 56 -   20MHz
104     CHAN(5300),             // 60 -   20MHz
105     CHAN(5320),             // 64 -   20MHz
106     CHAN(5500),             // 100 -  20MHz
107     CHAN(5520),             // 104 -  20MHz
108     CHAN(5540),             // 108 -  20MHz
109     CHAN(5560),             // 112 -  20MHz
110     CHAN(5580),             // 116 -  20MHz
111     CHAN(5600),             // 120 -  20MHz
112     CHAN(5620),             // 124 -  20MHz
113     CHAN(5640),             // 128 -  20MHz
114     CHAN(5660),             // 132 -  20MHz
115     CHAN(5680),             // 136 -  20MHz
116     CHAN(5700),             // 140 -  20MHz
117     CHAN(5720),             // 144 -  20MHz
118     CHAN(5745),             // 149 -  20MHz
119     CHAN(5765),             // 153 -  20MHz
120     CHAN(5785),             // 157 -  20MHz
121     CHAN(5805),             // 161 -  20MHz
122     CHAN(5825),             // 165 -  20MHz
123     // Extra channels defined only to be used for PHY measures.
124     // Enabled only if custregd and custchan parameters are set
125     CHAN(5190),
126     CHAN(5210),
127     CHAN(5230),
128     CHAN(5250),
129     CHAN(5270),
130     CHAN(5290),
131     CHAN(5310),
132     CHAN(5330),
133     CHAN(5340),
134     CHAN(5350),
135     CHAN(5360),
136     CHAN(5370),
137     CHAN(5380),
138     CHAN(5390),
139     CHAN(5400),
140     CHAN(5410),
141     CHAN(5420),
142     CHAN(5430),
143     CHAN(5440),
144     CHAN(5450),
145     CHAN(5460),
146     CHAN(5470),
147     CHAN(5480),
148     CHAN(5490),
149     CHAN(5510),
150     CHAN(5530),
151     CHAN(5550),
152     CHAN(5570),
153     CHAN(5590),
154     CHAN(5610),
155     CHAN(5630),
156     CHAN(5650),
157     CHAN(5670),
158     CHAN(5690),
159     CHAN(5710),
160     CHAN(5730),
161     CHAN(5750),
162     CHAN(5760),
163     CHAN(5770),
164     CHAN(5780),
165     CHAN(5790),
166     CHAN(5800),
167     CHAN(5810),
168     CHAN(5820),
169     CHAN(5830),
170     CHAN(5840),
171     CHAN(5850),
172     CHAN(5860),
173     CHAN(5870),
174     CHAN(5880),
175     CHAN(5890),
176     CHAN(5900),
177     CHAN(5910),
178     CHAN(5920),
179     CHAN(5930),
180     CHAN(5940),
181     CHAN(5950),
182     CHAN(5960),
183     CHAN(5970),
184 };
185 #endif
186
187 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
188 #if CONFIG_ECRNX_HE
189 static struct ieee80211_sband_iftype_data ecrnx_he_capa = {
190     .types_mask = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP),
191     .he_cap = ECRNX_HE_CAPABILITIES,
192 };
193 #endif
194 #endif
195
196 static struct ieee80211_supported_band ecrnx_band_2GHz = {
197     .channels   = ecrnx_2ghz_channels,
198     .n_channels = ARRAY_SIZE(ecrnx_2ghz_channels) - 13, // -13 to exclude extra channels
199     .bitrates   = ecrnx_ratetable,
200     .n_bitrates = ARRAY_SIZE(ecrnx_ratetable),
201     .ht_cap     = ECRNX_HT_CAPABILITIES,
202 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
203 #if CONFIG_ECRNX_HE
204     .iftype_data = &ecrnx_he_capa,
205     .n_iftype_data = 1,
206 #endif
207 #endif
208 };
209
210 #ifdef CONFIG_ECRNX_5G
211 static struct ieee80211_supported_band ecrnx_band_5GHz = {
212     .channels   = ecrnx_5ghz_channels,
213     .n_channels = ARRAY_SIZE(ecrnx_5ghz_channels) - 59, // -59 to exclude extra channels
214     .bitrates   = &ecrnx_ratetable[4],
215     .n_bitrates = ARRAY_SIZE(ecrnx_ratetable) - 4,
216     .ht_cap     = ECRNX_HT_CAPABILITIES,
217     .vht_cap    = ECRNX_VHT_CAPABILITIES,
218 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
219 #if CONFIG_ECRNX_HE
220     .iftype_data = &ecrnx_he_capa,
221     .n_iftype_data = 1,
222 #endif
223 #endif
224 };
225 #endif
226
227 static struct ieee80211_iface_limit ecrnx_limits[] = {
228     { .max = NX_VIRT_DEV_MAX, .types = BIT(NL80211_IFTYPE_AP) |
229                                        BIT(NL80211_IFTYPE_STATION)}
230 };
231
232 static struct ieee80211_iface_limit ecrnx_limits_dfs[] = {
233     { .max = NX_VIRT_DEV_MAX, .types = BIT(NL80211_IFTYPE_AP)}
234 };
235
236 static const struct ieee80211_iface_combination ecrnx_combinations[] = {
237     {
238         .limits                 = ecrnx_limits,
239         .n_limits               = ARRAY_SIZE(ecrnx_limits),
240         .num_different_channels = NX_CHAN_CTXT_CNT,
241         .max_interfaces         = NX_VIRT_DEV_MAX,
242     },
243     /* Keep this combination as the last one */
244     {
245         .limits                 = ecrnx_limits_dfs,
246         .n_limits               = ARRAY_SIZE(ecrnx_limits_dfs),
247         .num_different_channels = 1,
248         .max_interfaces         = NX_VIRT_DEV_MAX,
249 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
250         .radar_detect_widths = (BIT(NL80211_CHAN_WIDTH_20_NOHT) |
251                                 BIT(NL80211_CHAN_WIDTH_20) |
252                                 BIT(NL80211_CHAN_WIDTH_40) |
253                                 BIT(NL80211_CHAN_WIDTH_80)),
254 #endif
255     }
256 };
257
258 /* There isn't a lot of sense in it, but you can transmit anything you like */
259 static struct ieee80211_txrx_stypes
260 ecrnx_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
261     [NL80211_IFTYPE_STATION] = {
262         .tx = 0xffff,
263         .rx = (BIT(IEEE80211_STYPE_ACTION >> 4) |
264                BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
265                BIT(IEEE80211_STYPE_AUTH >> 4)),
266     },
267     [NL80211_IFTYPE_AP] = {
268         .tx = 0xffff,
269         .rx = (BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
270                BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
271                BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
272                BIT(IEEE80211_STYPE_DISASSOC >> 4) |
273                BIT(IEEE80211_STYPE_AUTH >> 4) |
274                BIT(IEEE80211_STYPE_DEAUTH >> 4) |
275                BIT(IEEE80211_STYPE_ACTION >> 4)),
276     },
277     [NL80211_IFTYPE_AP_VLAN] = {
278         /* copy AP */
279         .tx = 0xffff,
280         .rx = (BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
281                BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
282                BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
283                BIT(IEEE80211_STYPE_DISASSOC >> 4) |
284                BIT(IEEE80211_STYPE_AUTH >> 4) |
285                BIT(IEEE80211_STYPE_DEAUTH >> 4) |
286                BIT(IEEE80211_STYPE_ACTION >> 4)),
287     },
288     [NL80211_IFTYPE_P2P_CLIENT] = {
289         .tx = 0xffff,
290         .rx = (BIT(IEEE80211_STYPE_ACTION >> 4) |
291                BIT(IEEE80211_STYPE_PROBE_REQ >> 4)),
292     },
293     [NL80211_IFTYPE_P2P_GO] = {
294         .tx = 0xffff,
295         .rx = (BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
296                BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
297                BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
298                BIT(IEEE80211_STYPE_DISASSOC >> 4) |
299                BIT(IEEE80211_STYPE_AUTH >> 4) |
300                BIT(IEEE80211_STYPE_DEAUTH >> 4) |
301                BIT(IEEE80211_STYPE_ACTION >> 4)),
302     },
303     [NL80211_IFTYPE_P2P_DEVICE] = {
304         .tx = 0xffff,
305         .rx = (BIT(IEEE80211_STYPE_ACTION >> 4) |
306                BIT(IEEE80211_STYPE_PROBE_REQ >> 4)),
307     },
308     [NL80211_IFTYPE_MESH_POINT] = {
309         .tx = 0xffff,
310         .rx = (BIT(IEEE80211_STYPE_ACTION >> 4) |
311                BIT(IEEE80211_STYPE_AUTH >> 4) |
312                BIT(IEEE80211_STYPE_DEAUTH >> 4)),
313     },
314 };
315
316
317 static u32 cipher_suites[] = {
318     WLAN_CIPHER_SUITE_WEP40,
319     WLAN_CIPHER_SUITE_WEP104,
320     WLAN_CIPHER_SUITE_TKIP,
321     WLAN_CIPHER_SUITE_CCMP,
322     0, // reserved entries to enable AES-CMAC and/or SMS4
323     0,
324     0,
325     0,
326     0,
327 };
328 #define NB_RESERVED_CIPHER 5;
329
330 static const int ecrnx_ac2hwq[1][NL80211_NUM_ACS] = {
331     {
332         [NL80211_TXQ_Q_VO] = ECRNX_HWQ_VO,
333         [NL80211_TXQ_Q_VI] = ECRNX_HWQ_VI,
334         [NL80211_TXQ_Q_BE] = ECRNX_HWQ_BE,
335         [NL80211_TXQ_Q_BK] = ECRNX_HWQ_BK
336     }
337 };
338
339 const int ecrnx_tid2hwq[IEEE80211_NUM_TIDS] = {
340     ECRNX_HWQ_BE,
341     ECRNX_HWQ_BK,
342     ECRNX_HWQ_BK,
343     ECRNX_HWQ_BE,
344     ECRNX_HWQ_VI,
345     ECRNX_HWQ_VI,
346     ECRNX_HWQ_VO,
347     ECRNX_HWQ_VO,
348     /* TID_8 is used for management frames */
349     ECRNX_HWQ_VO,
350     /* At the moment, all others TID are mapped to BE */
351     ECRNX_HWQ_BE,
352     ECRNX_HWQ_BE,
353     ECRNX_HWQ_BE,
354     ECRNX_HWQ_BE,
355     ECRNX_HWQ_BE,
356     ECRNX_HWQ_BE,
357     ECRNX_HWQ_BE,
358 };
359
360 static const int ecrnx_hwq2uapsd[NL80211_NUM_ACS] = {
361     [ECRNX_HWQ_VO] = IEEE80211_WMM_IE_STA_QOSINFO_AC_VO,
362     [ECRNX_HWQ_VI] = IEEE80211_WMM_IE_STA_QOSINFO_AC_VI,
363     [ECRNX_HWQ_BE] = IEEE80211_WMM_IE_STA_QOSINFO_AC_BE,
364     [ECRNX_HWQ_BK] = IEEE80211_WMM_IE_STA_QOSINFO_AC_BK,
365 };
366
367 /*********************************************************************
368  * helper
369  *********************************************************************/
370 struct ecrnx_sta *ecrnx_get_sta(struct ecrnx_hw *ecrnx_hw, const u8 *mac_addr)
371 {
372     int i;
373
374     for (i = 0; i < NX_REMOTE_STA_MAX; i++) {
375         struct ecrnx_sta *sta = &ecrnx_hw->sta_table[i];
376         if (sta->valid && (memcmp(mac_addr, &sta->mac_addr, 6) == 0))
377             return sta;
378     }
379
380     return NULL;
381 }
382
383 void ecrnx_enable_wapi(struct ecrnx_hw *ecrnx_hw)
384 {
385     cipher_suites[ecrnx_hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_SMS4;
386     ecrnx_hw->wiphy->n_cipher_suites ++;
387     ecrnx_hw->wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;
388 }
389
390 void ecrnx_enable_mfp(struct ecrnx_hw *ecrnx_hw)
391 {
392     cipher_suites[ecrnx_hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_AES_CMAC;
393     ecrnx_hw->wiphy->n_cipher_suites ++;
394 }
395
396 void ecrnx_enable_gcmp(struct ecrnx_hw *ecrnx_hw)
397 {
398 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
399     cipher_suites[ecrnx_hw->wiphy->n_cipher_suites++] = WLAN_CIPHER_SUITE_CCMP_256;
400     cipher_suites[ecrnx_hw->wiphy->n_cipher_suites++] = WLAN_CIPHER_SUITE_GCMP;
401     cipher_suites[ecrnx_hw->wiphy->n_cipher_suites++] = WLAN_CIPHER_SUITE_GCMP_256;
402 #endif
403 }
404 u8 *ecrnx_build_bcn(struct ecrnx_bcn *bcn, struct cfg80211_beacon_data *new)
405 {
406     u8 *buf, *pos;
407
408     if (new->head) {
409         u8 *head = kmalloc(new->head_len, GFP_KERNEL);
410
411         if (!head)
412             return NULL;
413
414         if (bcn->head)
415             kfree(bcn->head);
416
417         bcn->head = head;
418         bcn->head_len = new->head_len;
419         memcpy(bcn->head, new->head, new->head_len);
420     }
421     if (new->tail) {
422         u8 *tail = kmalloc(new->tail_len, GFP_KERNEL);
423
424         if (!tail)
425             return NULL;
426
427         if (bcn->tail)
428             kfree(bcn->tail);
429
430         bcn->tail = tail;
431         bcn->tail_len = new->tail_len;
432         memcpy(bcn->tail, new->tail, new->tail_len);
433     }
434
435     if (!bcn->head)
436         return NULL;
437
438     bcn->tim_len = 6;
439     bcn->len = bcn->head_len + bcn->tail_len + bcn->ies_len + bcn->tim_len;
440
441     buf = kmalloc(bcn->len, GFP_KERNEL);
442     if (!buf)
443         return NULL;
444
445     // Build the beacon buffer
446     pos = buf;
447     memcpy(pos, bcn->head, bcn->head_len);
448     pos += bcn->head_len;
449     *pos++ = WLAN_EID_TIM;
450     *pos++ = 4;
451     *pos++ = 0;
452     *pos++ = bcn->dtim;
453     *pos++ = 0;
454     *pos++ = 0;
455     if (bcn->tail) {
456         memcpy(pos, bcn->tail, bcn->tail_len);
457         pos += bcn->tail_len;
458     }
459     if (bcn->ies) {
460         memcpy(pos, bcn->ies, bcn->ies_len);
461     }
462
463     return buf;
464 }
465
466
467 static void ecrnx_del_bcn(struct ecrnx_bcn *bcn)
468 {
469     if (bcn->head) {
470         kfree(bcn->head);
471         bcn->head = NULL;
472     }
473     bcn->head_len = 0;
474
475     if (bcn->tail) {
476         kfree(bcn->tail);
477         bcn->tail = NULL;
478     }
479     bcn->tail_len = 0;
480
481     if (bcn->ies) {
482         kfree(bcn->ies);
483         bcn->ies = NULL;
484     }
485     bcn->ies_len = 0;
486     bcn->tim_len = 0;
487     bcn->dtim = 0;
488     bcn->len = 0;
489 }
490
491 /**
492  * Link channel ctxt to a vif and thus increments count for this context.
493  */
494 void ecrnx_chanctx_link(struct ecrnx_vif *vif, u8 ch_idx,
495                        struct cfg80211_chan_def *chandef)
496 {
497     struct ecrnx_chanctx *ctxt;
498
499     if (ch_idx >= NX_CHAN_CTXT_CNT) {
500         WARN(1, "Invalid channel ctxt id %d", ch_idx);
501         return;
502     }
503
504     vif->ch_index = ch_idx;
505     ctxt = &vif->ecrnx_hw->chanctx_table[ch_idx];
506     ctxt->count++;
507
508     // For now chandef is NULL for STATION interface
509     if (chandef) {
510         if (!ctxt->chan_def.chan)
511             ctxt->chan_def = *chandef;
512         else {
513             // TODO. check that chandef is the same as the one already
514             // set for this ctxt
515         }
516     }
517 }
518
519 /**
520  * Unlink channel ctxt from a vif and thus decrements count for this context
521  */
522 void ecrnx_chanctx_unlink(struct ecrnx_vif *vif)
523 {
524     struct ecrnx_chanctx *ctxt;
525
526     if (vif->ch_index == ECRNX_CH_NOT_SET)
527         return;
528
529     ctxt = &vif->ecrnx_hw->chanctx_table[vif->ch_index];
530
531     if (ctxt->count == 0) {
532         WARN(1, "Chan ctxt ref count is already 0");
533     } else {
534         ctxt->count--;
535     }
536
537     if (ctxt->count == 0) {
538         if (vif->ch_index == vif->ecrnx_hw->cur_chanctx) {
539             /* If current chan ctxt is no longer linked to a vif
540                disable radar detection (no need to check if it was activated) */
541             ecrnx_radar_detection_enable(&vif->ecrnx_hw->radar,
542                                         ECRNX_RADAR_DETECT_DISABLE,
543                                         ECRNX_RADAR_RIU);
544         }
545         /* set chan to null, so that if this ctxt is relinked to a vif that
546            don't have channel information, don't use wrong information */
547         ctxt->chan_def.chan = NULL;
548     }
549     vif->ch_index = ECRNX_CH_NOT_SET;
550 }
551
552 int ecrnx_chanctx_valid(struct ecrnx_hw *ecrnx_hw, u8 ch_idx)
553 {
554     if (ch_idx >= NX_CHAN_CTXT_CNT ||
555         ecrnx_hw->chanctx_table[ch_idx].chan_def.chan == NULL) {
556         return 0;
557     }
558
559     return 1;
560 }
561
562 static void ecrnx_del_csa(struct ecrnx_vif *vif)
563 {
564     struct ecrnx_hw *ecrnx_hw = vif->ecrnx_hw;
565     struct ecrnx_csa *csa = vif->ap.csa;
566
567     if (!csa)
568         return;
569
570     ecrnx_ipc_elem_var_deallocs(ecrnx_hw, &csa->elem);
571     ecrnx_del_bcn(&csa->bcn);
572     kfree(csa);
573     vif->ap.csa = NULL;
574 }
575
576 static void ecrnx_csa_finish(struct work_struct *ws)
577 {
578     struct ecrnx_csa *csa = container_of(ws, struct ecrnx_csa, work);
579     struct ecrnx_vif *vif = csa->vif;
580     struct ecrnx_hw *ecrnx_hw = vif->ecrnx_hw;
581     int error = csa->status;
582
583     if (!error)
584         error = ecrnx_send_bcn_change(ecrnx_hw, vif->vif_index, csa->elem.dma_addr,
585                                      csa->bcn.len, csa->bcn.head_len,
586                                      csa->bcn.tim_len, NULL);
587
588     if (error){
589 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
590         cfg80211_stop_iface(ecrnx_hw->wiphy, &vif->wdev, GFP_KERNEL);
591 #else
592         cfg80211_disconnected(vif->ndev, 0, NULL, 0, 0, GFP_KERNEL);
593 #endif
594     }
595     else {
596         mutex_lock(&vif->wdev.mtx);
597         __acquire(&vif->wdev.mtx);
598         spin_lock_bh(&ecrnx_hw->cb_lock);
599         ecrnx_chanctx_unlink(vif);
600         ecrnx_chanctx_link(vif, csa->ch_idx, &csa->chandef);
601         if (ecrnx_hw->cur_chanctx == csa->ch_idx) {
602             ecrnx_radar_detection_enable_on_cur_channel(ecrnx_hw);
603             ecrnx_txq_vif_start(vif, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
604         } else
605             ecrnx_txq_vif_stop(vif, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
606         spin_unlock_bh(&ecrnx_hw->cb_lock);
607         cfg80211_ch_switch_notify(vif->ndev, &csa->chandef);
608         mutex_unlock(&vif->wdev.mtx);
609         __release(&vif->wdev.mtx);
610     }
611     ecrnx_del_csa(vif);
612 }
613
614 /**
615  * ecrnx_external_auth_enable - Enable external authentication on a vif
616  *
617  * @vif: VIF on which external authentication must be enabled
618  *
619  * External authentication requires to start TXQ for unknown STA in
620  * order to send auth frame pusehd by user space.
621  * Note: It is assumed that fw is on the correct channel.
622  */
623 void ecrnx_external_auth_enable(struct ecrnx_vif *vif)
624 {
625     vif->sta.flags |= ECRNX_STA_EXT_AUTH;
626     ecrnx_txq_unk_vif_init(vif);
627     ecrnx_txq_start(ecrnx_txq_vif_get(vif, NX_UNK_TXQ_TYPE), 0);
628 }
629
630 /**
631  * ecrnx_external_auth_disable - Disable external authentication on a vif
632  *
633  * @vif: VIF on which external authentication must be disabled
634  */
635 void ecrnx_external_auth_disable(struct ecrnx_vif *vif)
636 {
637     if (!(vif->sta.flags & ECRNX_STA_EXT_AUTH))
638         return;
639
640     vif->sta.flags &= ~ECRNX_STA_EXT_AUTH;
641     ecrnx_txq_unk_vif_deinit(vif);
642 }
643
644 /**
645  * ecrnx_update_mesh_power_mode -
646  *
647  * @vif: mesh VIF  for which power mode is updated
648  *
649  * Does nothing if vif is not a mesh point interface.
650  * Since firmware doesn't support one power save mode per link select the
651  * most "active" power mode among all mesh links.
652  * Indeed as soon as we have to be active on one link we might as well be
653  * active on all links.
654  *
655  * If there is no link then the power mode for next peer is used;
656  */
657 void ecrnx_update_mesh_power_mode(struct ecrnx_vif *vif)
658 {
659 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
660     enum nl80211_mesh_power_mode mesh_pm;
661     struct ecrnx_sta *sta;
662     struct mesh_config mesh_conf;
663     struct mesh_update_cfm cfm;
664     u32 mask;
665
666     if (ECRNX_VIF_TYPE(vif) != NL80211_IFTYPE_MESH_POINT)
667         return;
668
669     if (list_empty(&vif->ap.sta_list)) {
670         mesh_pm = vif->ap.next_mesh_pm;
671     } else {
672         mesh_pm = NL80211_MESH_POWER_DEEP_SLEEP;
673         list_for_each_entry(sta, &vif->ap.sta_list, list) {
674             if (sta->valid && (sta->mesh_pm < mesh_pm)) {
675                 mesh_pm = sta->mesh_pm;
676             }
677         }
678     }
679
680     if (mesh_pm == vif->ap.mesh_pm)
681         return;
682
683     mask = BIT(NL80211_MESHCONF_POWER_MODE - 1);
684     mesh_conf.power_mode = mesh_pm;
685     if (ecrnx_send_mesh_update_req(vif->ecrnx_hw, vif, mask, &mesh_conf, &cfm) ||
686         cfm.status)
687         return;
688
689     vif->ap.mesh_pm = mesh_pm;
690 #endif
691 }
692
693 void ecrnx_save_assoc_info_for_ft(struct ecrnx_vif *vif,
694                                  struct cfg80211_connect_params *sme)
695 {
696     int ies_len = sme->ie_len + sme->ssid_len + 2;
697     u8 *pos;
698     if (!vif->sta.ft_assoc_ies) {
699         if (!cfg80211_find_ie(WLAN_EID_MOBILITY_DOMAIN, sme->ie, sme->ie_len))
700             return;
701         vif->sta.ft_assoc_ies_len = ies_len;
702         vif->sta.ft_assoc_ies = kmalloc(ies_len, GFP_KERNEL);
703     } else if (vif->sta.ft_assoc_ies_len < ies_len) {
704         kfree(vif->sta.ft_assoc_ies);
705         vif->sta.ft_assoc_ies = kmalloc(ies_len, GFP_KERNEL);
706     }
707     if (!vif->sta.ft_assoc_ies)
708         return;
709     pos = vif->sta.ft_assoc_ies;
710     *pos++ = WLAN_EID_SSID;
711     *pos++ = sme->ssid_len;
712     memcpy(pos, sme->ssid, sme->ssid_len);
713     pos += sme->ssid_len;
714     memcpy(pos, sme->ie, sme->ie_len);
715     vif->sta.ft_assoc_ies_len = ies_len;
716 }
717 /**
718  * ecrnx_rsne_to_connect_params - Initialise cfg80211_connect_params from
719  * RSN element.
720  *
721  * @rsne: RSN element
722  * @sme: Structure cfg80211_connect_params to initialize
723  *
724  * The goal is only to initialize enough for ecrnx_send_sm_connect_req
725  */
726 int ecrnx_rsne_to_connect_params(const struct ecrnx_element *rsne,
727                                 struct cfg80211_connect_params *sme)
728 {
729     int len = rsne->datalen;
730     int clen;
731     const u8 *pos = rsne->data ;
732     if (len < 8)
733         return 1;
734
735     sme->crypto.control_port_no_encrypt = false;
736     sme->crypto.control_port = true;
737     sme->crypto.control_port_ethertype = cpu_to_be16(ETH_P_PAE);
738
739     pos += 2;
740     sme->crypto.cipher_group = ntohl(*((u32 *)pos));
741     pos += 4;
742     clen = le16_to_cpu(*((u16 *)pos)) * 4;
743     pos += 2;
744     len -= 8;
745     if (len < clen + 2)
746         return 1;
747     // only need one cipher suite
748     sme->crypto.n_ciphers_pairwise = 1;
749     sme->crypto.ciphers_pairwise[0] = ntohl(*((u32 *)pos));
750     pos += clen;
751     len -= clen;
752
753     // no need for AKM
754     clen = le16_to_cpu(*((u16 *)pos)) * 4;
755     pos += 2;
756     len -= 2;
757     if (len < clen)
758         return 1;
759     pos += clen;
760     len -= clen;
761
762     if (len < 4)
763         return 0;
764
765     pos += 2;
766     clen = le16_to_cpu(*((u16 *)pos)) * 16;
767     len -= 4;
768 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
769     if (len > clen)
770         sme->mfp = NL80211_MFP_REQUIRED;
771 #endif
772
773     return 0;
774 }
775
776 /*********************************************************************
777  * netdev callbacks
778  ********************************************************************/
779 /**
780  * int (*ndo_open)(struct net_device *dev);
781  *     This function is called when network device transistions to the up
782  *     state.
783  *
784  * - Start FW if this is the first interface opened
785  * - Add interface at fw level
786  */
787 static int ecrnx_open(struct net_device *dev)
788 {
789     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
790     struct ecrnx_hw *ecrnx_hw = ecrnx_vif->ecrnx_hw;
791     struct mm_add_if_cfm add_if_cfm;
792     int error = 0;
793
794     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
795
796     // Check if it is the first opened VIF
797     if (ecrnx_hw->vif_started == 0)
798     {
799         // Start the FW
800        if ((error = ecrnx_send_start(ecrnx_hw)))
801            return error;
802
803        /* Device is now started */
804        set_bit(ECRNX_DEV_STARTED, &ecrnx_hw->flags);
805     }
806
807     if (ecrnx_vif->up) {
808         netdev_info(dev, "Started repeatedly");
809         return error;
810     }
811
812     if (ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_AP_VLAN) {
813         /* For AP_vlan use same fw and drv indexes. We ensure that this index
814            will not be used by fw for another vif by taking index >= NX_VIRT_DEV_MAX */
815         add_if_cfm.inst_nbr = ecrnx_vif->drv_vif_index;
816         netif_tx_stop_all_queues(dev);
817     } else {
818         /* Forward the information to the LMAC,
819          *     p2p value not used in FMAC configuration, iftype is sufficient */
820         if ((error = ecrnx_send_add_if(ecrnx_hw, dev->dev_addr,
821                                       ECRNX_VIF_TYPE(ecrnx_vif), false, &add_if_cfm)))
822             return error;
823
824         if (add_if_cfm.status != 0) {
825             ECRNX_PRINT_CFM_ERR(add_if);
826             return -EIO;
827         }
828     }
829
830     /* Save the index retrieved from LMAC */
831     spin_lock_bh(&ecrnx_hw->cb_lock);
832     ecrnx_vif->vif_index = add_if_cfm.inst_nbr;
833     ecrnx_vif->up = true;
834     ecrnx_hw->vif_started++;
835     ecrnx_hw->vif_table[add_if_cfm.inst_nbr] = ecrnx_vif;
836     memset(ecrnx_hw->vif_table[add_if_cfm.inst_nbr]->rx_pn, 0, TID_MAX * sizeof(uint64_t));
837     spin_unlock_bh(&ecrnx_hw->cb_lock);
838
839     if (ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_MONITOR) {
840         ecrnx_hw->monitor_vif = ecrnx_vif->vif_index;
841         if (ecrnx_vif->ch_index != ECRNX_CH_NOT_SET) {
842             //Configure the monitor channel
843             error = ecrnx_send_config_monitor_req(ecrnx_hw,
844                                                  &ecrnx_hw->chanctx_table[ecrnx_vif->ch_index].chan_def,
845                                                  NULL);
846         }
847     }
848
849     netif_carrier_off(dev);
850
851     return error;
852 }
853
854 /**
855  * int (*ndo_stop)(struct net_device *dev);
856  *     This function is called when network device transistions to the down
857  *     state.
858  *
859  * - Remove interface at fw level
860  * - Reset FW if this is the last interface opened
861  */
862 static int ecrnx_close(struct net_device *dev)
863 {
864     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
865     struct ecrnx_hw *ecrnx_hw = ecrnx_vif->ecrnx_hw;
866
867     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
868
869     netdev_info(dev, "CLOSE");
870
871     ecrnx_radar_cancel_cac(&ecrnx_hw->radar);
872
873     spin_lock_bh(&ecrnx_hw->scan_req_lock);
874     /* Abort scan request on the vif */
875     if (ecrnx_hw->scan_request &&
876         ecrnx_hw->scan_request->wdev == &ecrnx_vif->wdev) {
877 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
878         struct cfg80211_scan_info info = {
879             .aborted = true,
880         };
881
882         cfg80211_scan_done(ecrnx_hw->scan_request, &info);
883 #else
884         cfg80211_scan_done(ecrnx_hw->scan_request, true);
885 #endif
886         ecrnx_hw->scan_request = NULL;
887     }
888
889     spin_unlock_bh(&ecrnx_hw->scan_req_lock);
890     ecrnx_send_remove_if(ecrnx_hw, ecrnx_vif->vif_index);
891
892     if (ecrnx_hw->roc && (ecrnx_hw->roc->vif == ecrnx_vif)) {
893         kfree(ecrnx_hw->roc);
894         /* Initialize RoC element pointer to NULL, indicate that RoC can be started */
895         ecrnx_hw->roc = NULL;
896     }
897
898     /* Ensure that we won't process disconnect ind */
899     spin_lock_bh(&ecrnx_hw->cb_lock);
900
901     ecrnx_vif->up = false;
902     if (netif_carrier_ok(dev)) {
903         if (ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_STATION ||
904             ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_P2P_CLIENT) {
905             if (ecrnx_vif->sta.ft_assoc_ies) {
906                 kfree(ecrnx_vif->sta.ft_assoc_ies);
907                 ecrnx_vif->sta.ft_assoc_ies = NULL;
908                 ecrnx_vif->sta.ft_assoc_ies_len = 0;
909             }
910             cfg80211_disconnected(dev, WLAN_REASON_DEAUTH_LEAVING,
911                                   NULL, 0, true, GFP_ATOMIC);
912             if (ecrnx_vif->sta.ap) {
913                 ecrnx_txq_sta_deinit(ecrnx_hw, ecrnx_vif->sta.ap);
914                 ecrnx_txq_tdls_vif_deinit(ecrnx_vif);
915             }
916             netif_tx_stop_all_queues(dev);
917             netif_carrier_off(dev);
918         } else if (ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_AP_VLAN) {
919             netif_carrier_off(dev);
920         } else {
921             netdev_warn(dev, "AP not stopped when disabling interface");
922         }
923     }
924
925     ecrnx_hw->vif_table[ecrnx_vif->vif_index] = NULL;
926     spin_unlock_bh(&ecrnx_hw->cb_lock);
927
928     ecrnx_chanctx_unlink(ecrnx_vif);
929
930     if (ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_MONITOR)
931         ecrnx_hw->monitor_vif = ECRNX_INVALID_VIF;
932
933     ecrnx_hw->vif_started--;
934     if (ecrnx_hw->vif_started == 0) {
935 #ifndef CONFIG_ECRNX_ESWIN
936         /* This also lets both ipc sides remain in sync before resetting */
937         ecrnx_ipc_tx_drain(ecrnx_hw);
938 #endif
939         ecrnx_send_reset(ecrnx_hw);
940
941         // Set parameters to firmware
942         ecrnx_send_me_config_req(ecrnx_hw);
943
944         // Set channel parameters to firmware
945         ecrnx_send_me_chan_config_req(ecrnx_hw);
946
947         clear_bit(ECRNX_DEV_STARTED, &ecrnx_hw->flags);
948     }
949
950     return 0;
951 }
952
953 /**
954  * struct net_device_stats* (*ndo_get_stats)(struct net_device *dev);
955  *      Called when a user wants to get the network device usage
956  *      statistics. Drivers must do one of the following:
957  *      1. Define @ndo_get_stats64 to fill in a zero-initialised
958  *         rtnl_link_stats64 structure passed by the caller.
959  *      2. Define @ndo_get_stats to update a net_device_stats structure
960  *         (which should normally be dev->stats) and return a pointer to
961  *         it. The structure may be changed asynchronously only if each
962  *         field is written atomically.
963  *      3. Update dev->stats asynchronously and atomically, and define
964  *         neither operation.
965  */
966 static struct net_device_stats *ecrnx_get_stats(struct net_device *dev)
967 {
968     struct ecrnx_vif *vif = netdev_priv(dev);
969
970     return &vif->net_stats;
971 }
972
973 /**
974  * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb,
975  *                         struct net_device *sb_dev);
976  *      Called to decide which queue to when device supports multiple
977  *      transmit queues.
978  */
979 u16 ecrnx_select_queue(struct net_device *dev, struct sk_buff *skb,
980                       struct net_device *sb_dev)
981 {
982     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
983     return ecrnx_select_txq(ecrnx_vif, skb);
984 }
985
986 /**
987  * int (*ndo_set_mac_address)(struct net_device *dev, void *addr);
988  *      This function  is called when the Media Access Control address
989  *      needs to be changed. If this interface is not defined, the
990  *      mac address can not be changed.
991  */
992 static int ecrnx_set_mac_address(struct net_device *dev, void *addr)
993 {
994     struct sockaddr *sa = addr;
995     int ret;
996
997     ret = eth_mac_addr(dev, sa);
998
999     return ret;
1000 }
1001
1002 int ecrnx_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1003 {
1004     //struct iwreq *wrq = (struct iwreq *)rq;
1005     int ret = 0;
1006
1007     switch (cmd) {
1008      case (SIOCDEVPRIVATE+1):
1009       //ret = ecrnx_android_priv_cmd(dev, rq, cmd);
1010         break;
1011      default:
1012         ret = -EOPNOTSUPP;
1013         break;
1014     }
1015
1016  return ret;
1017 }
1018
1019 static const struct net_device_ops ecrnx_netdev_ops = {
1020     .ndo_open               = ecrnx_open,
1021     .ndo_stop               = ecrnx_close,
1022     .ndo_start_xmit         = ecrnx_start_xmit,
1023     .ndo_get_stats          = ecrnx_get_stats,
1024     .ndo_select_queue       = ecrnx_select_queue,
1025     .ndo_set_mac_address    = ecrnx_set_mac_address,
1026     .ndo_do_ioctl           = ecrnx_ioctl,
1027 //    .ndo_set_features       = ecrnx_set_features,
1028 //    .ndo_set_rx_mode        = ecrnx_set_multicast_list,
1029 };
1030
1031 static const struct net_device_ops ecrnx_netdev_monitor_ops = {
1032     .ndo_open               = ecrnx_open,
1033     .ndo_stop               = ecrnx_close,
1034     .ndo_get_stats          = ecrnx_get_stats,
1035     .ndo_set_mac_address    = ecrnx_set_mac_address,
1036 };
1037
1038 #ifdef CONFIG_WIRELESS_EXT
1039 extern const struct iw_handler_def  ecrnx_wext_handler_def;
1040 #endif
1041
1042 static void ecrnx_netdev_setup(struct net_device *dev)
1043 {
1044     ether_setup(dev);
1045     dev->priv_flags &= ~IFF_TX_SKB_SHARING;
1046     dev->netdev_ops = &ecrnx_netdev_ops;
1047 #ifdef CONFIG_WIRELESS_EXT
1048     dev->wireless_handlers = &ecrnx_wext_handler_def;
1049 #endif
1050 #if LINUX_VERSION_CODE <  KERNEL_VERSION(4, 12, 0)
1051     dev->destructor = free_netdev;
1052 #else
1053     dev->needs_free_netdev = true;
1054 #endif
1055     dev->watchdog_timeo = ECRNX_TX_LIFETIME_MS;
1056     dev->needed_headroom = ECRNX_TX_MAX_HEADROOM;
1057
1058 #ifdef CONFIG_ECRNX_AMSDUS_TX
1059     dev->needed_headroom = max(dev->needed_headroom,
1060                                (unsigned short)(sizeof(struct ecrnx_amsdu_txhdr)
1061                                                 + sizeof(struct ethhdr) + 4
1062                                                 + sizeof(rfc1042_header) + 2));
1063 #endif /* CONFIG_ECRNX_AMSDUS_TX */
1064
1065     dev->hw_features = 0;
1066 }
1067
1068 /*********************************************************************
1069  * Cfg80211 callbacks (and helper)
1070  *********************************************************************/
1071 static struct wireless_dev *ecrnx_interface_add(struct ecrnx_hw *ecrnx_hw,
1072                                                const char *name,
1073                                                unsigned char name_assign_type,
1074                                                enum nl80211_iftype type,
1075                                                struct vif_params *params)
1076 {
1077     struct net_device *ndev;
1078     struct ecrnx_vif *vif;
1079     int min_idx, max_idx;
1080     int vif_idx = -1;
1081     int i;
1082
1083     // Look for an available VIF
1084     if (type == NL80211_IFTYPE_AP_VLAN) {
1085         min_idx = NX_VIRT_DEV_MAX;
1086         max_idx = NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX;
1087     } else {
1088         min_idx = 0;
1089         max_idx = NX_VIRT_DEV_MAX;
1090     }
1091
1092     for (i = min_idx; i < max_idx; i++) {
1093         if ((ecrnx_hw->avail_idx_map) & BIT(i)) {
1094             vif_idx = i;
1095             break;
1096         }
1097     }
1098     if (vif_idx < 0)
1099         return NULL;
1100
1101     #ifndef CONFIG_ECRNX_MON_DATA
1102     list_for_each_entry(vif, &ecrnx_hw->vifs, list) {
1103         // Check if monitor interface already exists or type is monitor
1104         if ((ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_MONITOR) ||
1105            (type == NL80211_IFTYPE_MONITOR)) {
1106             wiphy_err(ecrnx_hw->wiphy,
1107                     "Monitor+Data interface support (MON_DATA) disabled\n");
1108             return NULL;
1109         }
1110     }
1111     #endif
1112
1113     ndev = alloc_netdev_mqs(sizeof(*vif), name, name_assign_type,
1114                             ecrnx_netdev_setup, NX_NB_NDEV_TXQ, 1);
1115     if (!ndev)
1116         return NULL;
1117
1118     vif = netdev_priv(ndev);
1119     ndev->ieee80211_ptr = &vif->wdev;
1120     vif->wdev.wiphy = ecrnx_hw->wiphy;
1121     vif->ecrnx_hw = ecrnx_hw;
1122     vif->ndev = ndev;
1123     vif->drv_vif_index = vif_idx;
1124     SET_NETDEV_DEV(ndev, wiphy_dev(vif->wdev.wiphy));
1125     vif->wdev.netdev = ndev;
1126     vif->wdev.iftype = type;
1127     vif->up = false;
1128     vif->ch_index = ECRNX_CH_NOT_SET;
1129     vif->generation = 0;
1130     memset(&vif->net_stats, 0, sizeof(vif->net_stats));
1131     memset(vif->rx_pn, 0, TID_MAX * sizeof(uint64_t));
1132
1133     switch (type) {
1134     case NL80211_IFTYPE_STATION:
1135     case NL80211_IFTYPE_P2P_CLIENT:
1136         vif->sta.flags = 0;
1137         vif->sta.ap = NULL;
1138         vif->sta.tdls_sta = NULL;
1139         vif->sta.ft_assoc_ies = NULL;
1140         vif->sta.ft_assoc_ies_len = 0;
1141         break;
1142     case NL80211_IFTYPE_MESH_POINT:
1143         INIT_LIST_HEAD(&vif->ap.mpath_list);
1144         INIT_LIST_HEAD(&vif->ap.proxy_list);
1145 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
1146         vif->ap.mesh_pm = NL80211_MESH_POWER_ACTIVE;
1147         vif->ap.next_mesh_pm = NL80211_MESH_POWER_ACTIVE;
1148 #endif
1149         break;
1150     case NL80211_IFTYPE_AP:
1151     case NL80211_IFTYPE_P2P_GO:
1152         INIT_LIST_HEAD(&vif->ap.sta_list);
1153         memset(&vif->ap.bcn, 0, sizeof(vif->ap.bcn));
1154         vif->ap.flags = 0;
1155         break;
1156     case NL80211_IFTYPE_AP_VLAN:
1157     {
1158         struct ecrnx_vif *master_vif;
1159         bool found = false;
1160         list_for_each_entry(master_vif, &ecrnx_hw->vifs, list) {
1161             if ((ECRNX_VIF_TYPE(master_vif) == NL80211_IFTYPE_AP)
1162 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
1163                 && !(!memcmp(master_vif->ndev->dev_addr, params->macaddr,
1164                            ETH_ALEN))
1165 #endif
1166                  ) {
1167                  found=true;
1168                  break;
1169             }
1170         }
1171
1172         if (!found)
1173             goto err;
1174
1175          vif->ap_vlan.master = master_vif;
1176          vif->ap_vlan.sta_4a = NULL;
1177          break;
1178     }
1179     case NL80211_IFTYPE_MONITOR:
1180         ndev->type = ARPHRD_IEEE80211_RADIOTAP;
1181         ndev->netdev_ops = &ecrnx_netdev_monitor_ops;
1182         break;
1183     default:
1184         break;
1185     }
1186
1187 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
1188     if (type == NL80211_IFTYPE_AP_VLAN)
1189         memcpy(ndev->dev_addr, params->macaddr, ETH_ALEN);
1190     else 
1191 #endif
1192     {
1193         memcpy(ndev->dev_addr, ecrnx_hw->wiphy->perm_addr, ETH_ALEN);
1194         ndev->dev_addr[5] ^= vif_idx;
1195     }
1196
1197     if (params) {
1198         vif->use_4addr = params->use_4addr;
1199         ndev->ieee80211_ptr->use_4addr = params->use_4addr;
1200     } else
1201         vif->use_4addr = false;
1202
1203
1204     if (register_netdevice(ndev))
1205         goto err;
1206
1207     spin_lock_bh(&ecrnx_hw->cb_lock);
1208     list_add_tail(&vif->list, &ecrnx_hw->vifs);
1209     spin_unlock_bh(&ecrnx_hw->cb_lock);
1210     ecrnx_hw->avail_idx_map &= ~BIT(vif_idx);
1211
1212 //#if defined(CONFIG_ECRNX_ESWIN_SDIO) || defined(CONFIG_ECRNX_ESWIN_USB)
1213     init_waitqueue_head(&vif->rxdataq);
1214 //#endif
1215
1216     return &vif->wdev;
1217
1218 err:
1219     free_netdev(ndev);
1220     return NULL;
1221 }
1222
1223
1224 /*
1225  * @brief Retrieve the ecrnx_sta object allocated for a given MAC address
1226  * and a given role.
1227  */
1228 static struct ecrnx_sta *ecrnx_retrieve_sta(struct ecrnx_hw *ecrnx_hw,
1229                                           struct ecrnx_vif *ecrnx_vif, u8 *addr,
1230                                           __le16 fc, bool ap)
1231 {
1232     if (ap) {
1233         /* only deauth, disassoc and action are bufferable MMPDUs */
1234         bool bufferable = ieee80211_is_deauth(fc) ||
1235                           ieee80211_is_disassoc(fc) ||
1236                           ieee80211_is_action(fc);
1237
1238         /* Check if the packet is bufferable or not */
1239         if (bufferable)
1240         {
1241             /* Check if address is a broadcast or a multicast address */
1242             if (is_broadcast_ether_addr(addr) || is_multicast_ether_addr(addr)) {
1243                 /* Returned STA pointer */
1244                 struct ecrnx_sta *ecrnx_sta = &ecrnx_hw->sta_table[ecrnx_vif->ap.bcmc_index];
1245
1246                 if (ecrnx_sta->valid)
1247                     return ecrnx_sta;
1248             } else {
1249                 /* Returned STA pointer */
1250                 struct ecrnx_sta *ecrnx_sta;
1251
1252                 /* Go through list of STAs linked with the provided VIF */
1253                 list_for_each_entry(ecrnx_sta, &ecrnx_vif->ap.sta_list, list) {
1254                     if (ecrnx_sta->valid &&
1255                         ether_addr_equal(ecrnx_sta->mac_addr, addr)) {
1256                         /* Return the found STA */
1257                         return ecrnx_sta;
1258                     }
1259                 }
1260             }
1261         }
1262     } else {
1263         return ecrnx_vif->sta.ap;
1264     }
1265
1266     return NULL;
1267 }
1268
1269 /**
1270  * @add_virtual_intf: create a new virtual interface with the given name,
1271  *      must set the struct wireless_dev's iftype. Beware: You must create
1272  *      the new netdev in the wiphy's network namespace! Returns the struct
1273  *      wireless_dev, or an ERR_PTR. For P2P device wdevs, the driver must
1274  *      also set the address member in the wdev.
1275  */
1276 static struct wireless_dev *ecrnx_cfg80211_add_iface(struct wiphy *wiphy,
1277                                                     const char *name,
1278                                                     unsigned char name_assign_type,
1279                                                     enum nl80211_iftype type,
1280                                                     struct vif_params *params)
1281 {
1282     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1283     struct wireless_dev *wdev;
1284
1285     wdev = ecrnx_interface_add(ecrnx_hw, name, name_assign_type, type, params);
1286
1287     if (!wdev)
1288         return ERR_PTR(-EINVAL);
1289
1290     return wdev;
1291 }
1292
1293 /**
1294  * @del_virtual_intf: remove the virtual interface
1295  */
1296 static int ecrnx_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
1297 {
1298     struct net_device *dev = wdev->netdev;
1299     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
1300     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1301
1302     netdev_info(dev, "Remove Interface");
1303
1304     if (dev->reg_state == NETREG_REGISTERED) {
1305       ECRNX_DBG("%s-%d:unregister_netdevice \n", __func__, __LINE__);
1306         /* Will call ecrnx_close if interface is UP */
1307         unregister_netdevice(dev);
1308     }
1309
1310     spin_lock_bh(&ecrnx_hw->cb_lock);
1311     list_del(&ecrnx_vif->list);
1312     spin_unlock_bh(&ecrnx_hw->cb_lock);
1313     ecrnx_hw->avail_idx_map |= BIT(ecrnx_vif->drv_vif_index);
1314     ecrnx_vif->ndev = NULL;
1315
1316     /* Clear the priv in adapter */
1317     dev->ieee80211_ptr = NULL;
1318
1319     return 0;
1320 }
1321
1322 static int ecrnx_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev);
1323 static int ecrnx_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
1324                                     u16 reason_code);
1325
1326 /**
1327  * @change_virtual_intf: change type/configuration of virtual interface,
1328  *      keep the struct wireless_dev's iftype updated.
1329  */
1330 static int ecrnx_cfg80211_change_iface(struct wiphy *wiphy,
1331                                       struct net_device *dev,
1332                                       enum nl80211_iftype type,
1333                                       struct vif_params *params)
1334 {
1335 #ifndef CONFIG_ECRNX_MON_DATA
1336     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1337 #endif
1338     struct ecrnx_vif *vif = netdev_priv(dev);
1339
1340
1341     ECRNX_PRINT("%s:dev:0x%p, type:%d, vif->up:%d \n", __func__, dev, type, vif->up);
1342
1343     if (vif->up)
1344     {
1345         if((ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_AP) || (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_GO))
1346         {
1347             ecrnx_cfg80211_stop_ap(wiphy, dev);
1348         }
1349         else if((ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_STATION) || (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_CLIENT))
1350         {
1351             ecrnx_cfg80211_disconnect(wiphy, dev, WLAN_REASON_DEAUTH_LEAVING);
1352         }
1353         ECRNX_ERR("ecrnx_cfg80211_change_iface: -EBUSY \n");
1354         ecrnx_close(dev);
1355         //return (-EBUSY);
1356     }
1357
1358 #ifndef CONFIG_ECRNX_MON_DATA
1359     if ((type == NL80211_IFTYPE_MONITOR) &&
1360        (ECRNX_VIF_TYPE(vif) != NL80211_IFTYPE_MONITOR)) {
1361         struct ecrnx_vif *vif_el;
1362         list_for_each_entry(vif_el, &ecrnx_hw->vifs, list) {
1363             // Check if data interface already exists
1364             if ((vif_el != vif) &&
1365                (ECRNX_VIF_TYPE(vif) != NL80211_IFTYPE_MONITOR)) {
1366                 wiphy_err(ecrnx_hw->wiphy,
1367                         "Monitor+Data interface support (MON_DATA) disabled\n");
1368                 return -EIO;
1369             }
1370         }
1371     }
1372 #endif
1373
1374     // Reset to default case (i.e. not monitor)
1375     dev->type = ARPHRD_ETHER;
1376     dev->netdev_ops = &ecrnx_netdev_ops;
1377
1378     switch (type) {
1379     case NL80211_IFTYPE_STATION:
1380     case NL80211_IFTYPE_P2P_CLIENT:
1381         vif->sta.flags = 0;
1382         vif->sta.ap = NULL;
1383         vif->sta.tdls_sta = NULL;
1384         vif->sta.ft_assoc_ies = NULL;
1385         vif->sta.ft_assoc_ies_len = 0;
1386         break;
1387     case NL80211_IFTYPE_MESH_POINT:
1388         INIT_LIST_HEAD(&vif->ap.mpath_list);
1389         INIT_LIST_HEAD(&vif->ap.proxy_list);
1390         break;
1391     case NL80211_IFTYPE_AP:
1392     case NL80211_IFTYPE_P2P_GO:
1393         INIT_LIST_HEAD(&vif->ap.sta_list);
1394         memset(&vif->ap.bcn, 0, sizeof(vif->ap.bcn));
1395         vif->ap.flags = 0;
1396         break;
1397     case NL80211_IFTYPE_AP_VLAN:
1398         return -EPERM;
1399     case NL80211_IFTYPE_MONITOR:
1400         dev->type = ARPHRD_IEEE80211_RADIOTAP;
1401         dev->netdev_ops = &ecrnx_netdev_monitor_ops;
1402         break;
1403     default:
1404         break;
1405     }
1406
1407     vif->generation = 0;
1408     vif->wdev.iftype = type;
1409     if (params->use_4addr != -1)
1410         vif->use_4addr = params->use_4addr;
1411
1412     if (!vif->up)
1413     {
1414         ecrnx_open(dev);
1415     }
1416
1417     return 0;
1418 }
1419
1420 /*
1421  * GavinGao
1422  * Used as P2P_DEVICE mode
1423  */
1424 static int ecrnx_cfg80211_start_p2p_device(struct wiphy *wiphy,
1425                                       struct wireless_dev *wdev)
1426 {
1427         ECRNX_PRINT("rwnx_cfg80211_start_p2p_device\n");
1428         return 0;
1429 }
1430
1431 static void ecrnx_cfg80211_stop_p2p_device(struct wiphy *wiphy,
1432                                       struct wireless_dev *wdev)
1433 {
1434         //TODO
1435 }
1436 /* Used as P2P_DEVICE mode*/
1437                                           
1438
1439 /**
1440  * @scan: Request to do a scan. If returning zero, the scan request is given
1441  *      the driver, and will be valid until passed to cfg80211_scan_done().
1442  *      For scan results, call cfg80211_inform_bss(); you can call this outside
1443  *      the scan/scan_done bracket too.
1444  */
1445 static int ecrnx_cfg80211_scan(struct wiphy *wiphy,
1446                               struct cfg80211_scan_request *request)
1447 {
1448     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1449     struct ecrnx_vif *ecrnx_vif = container_of(request->wdev, struct ecrnx_vif,
1450                                              wdev);
1451     int error;
1452
1453     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1454
1455     if(!ecrnx_hw->scan_request){
1456         ecrnx_hw->scan_request = request;
1457         ECRNX_PRINT("%s:scan_request:0x%p \n", __func__, request);
1458         if ((error = ecrnx_send_scanu_req(ecrnx_hw, ecrnx_vif, request))){
1459             ECRNX_PRINT("scan message send error!!\n");
1460             ecrnx_hw->scan_request = NULL;
1461             return error;       
1462         }
1463     }else{
1464         ECRNX_PRINT("scan is already running!!\n");
1465     }
1466     ECRNX_DBG("send finish:ecrnx_cfg80211_scan \n");
1467
1468     return 0;
1469 }
1470
1471 static void ecrnx_cfg80211_abort_scan(struct wiphy *wiphy,
1472                               struct wireless_dev *wdev)
1473 {
1474     u8_l ret = 0;
1475     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1476     struct ecrnx_vif *ecrnx_vif = container_of(wdev, struct ecrnx_vif,
1477                                              wdev);
1478
1479     //mutex_lock(&ecrnx_hw->mutex);
1480     ECRNX_PRINT("%s:ecrnx_hw->scan_request:0x%p \n", __func__, ecrnx_hw->scan_request);
1481
1482     if(!ecrnx_hw->scan_request){
1483         ECRNX_ERR("no scan is running, don't need abort! \n");
1484         goto out;
1485     }
1486
1487     if(wdev->iftype != NL80211_IFTYPE_STATION){
1488         ECRNX_ERR("abort scan ignored, iftype(%d)\n", wdev->iftype);
1489         goto out;
1490     }
1491
1492     if(wdev != ecrnx_hw->scan_request->wdev){
1493         ECRNX_ERR("abort scan was called on the wrong iface\n");
1494         goto out;
1495     }
1496
1497     ret = ecrnx_send_scanu_cancel_req(ecrnx_hw, ecrnx_vif);
1498
1499 out:
1500     //mutex_unlock(&ecrnx_hw->mutex);
1501     return;
1502 }
1503
1504 /**
1505  * @add_key: add a key with the given parameters. @mac_addr will be %NULL
1506  *      when adding a group key.
1507  */
1508 static int ecrnx_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
1509                                  u8 key_index, bool pairwise, const u8 *mac_addr,
1510                                  struct key_params *params)
1511 {
1512     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1513     struct ecrnx_vif *vif = netdev_priv(netdev);
1514     int i, error = 0;
1515     struct mm_key_add_cfm key_add_cfm;
1516     u8_l cipher = 0;
1517     struct ecrnx_sta *sta = NULL;
1518     struct ecrnx_key *ecrnx_key;
1519
1520     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1521
1522     if (mac_addr) {
1523         sta = ecrnx_get_sta(ecrnx_hw, mac_addr);
1524         if (!sta)
1525             return -EINVAL;
1526         ecrnx_key = &sta->key;
1527     }
1528     else
1529         ecrnx_key = &vif->key[key_index];
1530
1531     /* Retrieve the cipher suite selector */
1532     switch (params->cipher) {
1533     case WLAN_CIPHER_SUITE_WEP40:
1534         cipher = MAC_CIPHER_WEP40;
1535         break;
1536     case WLAN_CIPHER_SUITE_WEP104:
1537         cipher = MAC_CIPHER_WEP104;
1538         break;
1539     case WLAN_CIPHER_SUITE_TKIP:
1540         cipher = MAC_CIPHER_TKIP;
1541         break;
1542     case WLAN_CIPHER_SUITE_CCMP:
1543         cipher = MAC_CIPHER_CCMP;
1544         break;
1545     case WLAN_CIPHER_SUITE_AES_CMAC:
1546         cipher = MAC_CIPHER_BIP_CMAC_128;
1547         break;
1548     case WLAN_CIPHER_SUITE_SMS4:
1549     {
1550         // Need to reverse key order
1551         u8 tmp, *key = (u8 *)params->key;
1552         cipher = MAC_CIPHER_WPI_SMS4;
1553         for (i = 0; i < WPI_SUBKEY_LEN/2; i++) {
1554             tmp = key[i];
1555             key[i] = key[WPI_SUBKEY_LEN - 1 - i];
1556             key[WPI_SUBKEY_LEN - 1 - i] = tmp;
1557         }
1558         for (i = 0; i < WPI_SUBKEY_LEN/2; i++) {
1559             tmp = key[i + WPI_SUBKEY_LEN];
1560             key[i + WPI_SUBKEY_LEN] = key[WPI_KEY_LEN - 1 - i];
1561             key[WPI_KEY_LEN - 1 - i] = tmp;
1562         }
1563         break;
1564     }
1565     case WLAN_CIPHER_SUITE_GCMP:
1566         cipher = MAC_CIPHER_GCMP_128;
1567         break;
1568 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
1569     case WLAN_CIPHER_SUITE_GCMP_256:
1570         cipher = MAC_CIPHER_GCMP_256;
1571         break;
1572     case WLAN_CIPHER_SUITE_CCMP_256:
1573         cipher = MAC_CIPHER_CCMP_256;
1574         break;
1575 #endif
1576     default:
1577         return -EINVAL;
1578     }
1579
1580     if ((error = ecrnx_send_key_add(ecrnx_hw, vif->vif_index,
1581                                    (sta ? sta->sta_idx : 0xFF), pairwise,
1582                                    (u8 *)params->key, params->key_len,
1583                                    key_index, cipher, &key_add_cfm)))
1584         return error;
1585
1586     if (key_add_cfm.status != 0) {
1587         ECRNX_PRINT_CFM_ERR(key_add);
1588         return -EIO;
1589     }
1590
1591     /* Save the index retrieved from LMAC */
1592     ecrnx_key->hw_idx = key_add_cfm.hw_key_idx;
1593
1594     return 0;
1595 }
1596
1597 /**
1598  * @get_key: get information about the key with the given parameters.
1599  *      @mac_addr will be %NULL when requesting information for a group
1600  *      key. All pointers given to the @callback function need not be valid
1601  *      after it returns. This function should return an error if it is
1602  *      not possible to retrieve the key, -ENOENT if it doesn't exist.
1603  *
1604  */
1605 static int ecrnx_cfg80211_get_key(struct wiphy *wiphy, struct net_device *netdev,
1606                                  u8 key_index, bool pairwise, const u8 *mac_addr,
1607                                  void *cookie,
1608                                  void (*callback)(void *cookie, struct key_params*))
1609 {
1610     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1611
1612     return -1;
1613 }
1614
1615
1616 /**
1617  * @del_key: remove a key given the @mac_addr (%NULL for a group key)
1618  *      and @key_index, return -ENOENT if the key doesn't exist.
1619  */
1620 static int ecrnx_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
1621                                  u8 key_index, bool pairwise, const u8 *mac_addr)
1622 {
1623     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1624     struct ecrnx_vif *vif = netdev_priv(netdev);
1625     int error;
1626     struct ecrnx_sta *sta = NULL;
1627     struct ecrnx_key *ecrnx_key;
1628
1629     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1630     if (mac_addr) {
1631         sta = ecrnx_get_sta(ecrnx_hw, mac_addr);
1632         if (!sta)
1633             return -EINVAL;
1634         ecrnx_key = &sta->key;
1635     }
1636     else
1637         ecrnx_key = &vif->key[key_index];
1638
1639     error = ecrnx_send_key_del(ecrnx_hw, ecrnx_key->hw_idx);
1640
1641     return error;
1642 }
1643
1644 /**
1645  * @set_default_key: set the default key on an interface
1646  */
1647 static int ecrnx_cfg80211_set_default_key(struct wiphy *wiphy,
1648                                          struct net_device *netdev,
1649                                          u8 key_index, bool unicast, bool multicast)
1650 {
1651     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1652
1653     return 0;
1654 }
1655
1656 /**
1657  * @set_default_mgmt_key: set the default management frame key on an interface
1658  */
1659 static int ecrnx_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,
1660                                               struct net_device *netdev,
1661                                               u8 key_index)
1662 {
1663     return 0;
1664 }
1665
1666 /**
1667  * @connect: Connect to the ESS with the specified parameters. When connected,
1668  *      call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS.
1669  *      If the connection fails for some reason, call cfg80211_connect_result()
1670  *      with the status from the AP.
1671  *      (invoked with the wireless_dev mutex held)
1672  */
1673 static int ecrnx_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
1674                                  struct cfg80211_connect_params *sme)
1675 {
1676     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1677     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
1678     struct sm_connect_cfm sm_connect_cfm;
1679     int error = 0;
1680
1681     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1682
1683     /* For SHARED-KEY authentication, must install key first */
1684     if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY && sme->key)
1685     {
1686         struct key_params key_params;
1687         key_params.key = sme->key;
1688         key_params.seq = NULL;
1689         key_params.key_len = sme->key_len;
1690         key_params.seq_len = 0;
1691         key_params.cipher = sme->crypto.cipher_group;
1692         ecrnx_cfg80211_add_key(wiphy, dev, sme->key_idx, false, NULL, &key_params);
1693     }
1694 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
1695     else if ((sme->auth_type == NL80211_AUTHTYPE_SAE) &&
1696              !(sme->flags & CONNECT_REQ_EXTERNAL_AUTH_SUPPORT)) {
1697         netdev_err(dev, "Doesn't support SAE without external authentication\n");
1698         return -EINVAL;
1699     }
1700 #endif
1701
1702     /* Forward the information to the LMAC */
1703     if ((error = ecrnx_send_sm_connect_req(ecrnx_hw, ecrnx_vif, sme, &sm_connect_cfm)))
1704         return error;
1705     ECRNX_PRINT("%s:bssid:%pM, send status:%d\n", __func__, sme->bssid, sm_connect_cfm.status);
1706
1707     // Check the status
1708     switch (sm_connect_cfm.status)
1709     {
1710         case CO_OK:
1711             ecrnx_save_assoc_info_for_ft(ecrnx_vif, sme);
1712             error = 0;
1713             break;
1714         case CO_BUSY:
1715             error = -EINPROGRESS;
1716             break;
1717         case CO_BAD_PARAM:
1718             error = -EINVAL;
1719             break;
1720         case CO_OP_IN_PROGRESS:
1721             error = -EALREADY;
1722             break;
1723         default:
1724             error = -EIO;
1725             break;
1726     }
1727
1728     return error;
1729 }
1730
1731 /**
1732  * @disconnect: Disconnect from the BSS/ESS.
1733  *      (invoked with the wireless_dev mutex held)
1734  */
1735 static int ecrnx_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
1736                                     u16 reason_code)
1737 {
1738     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1739     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
1740
1741     ECRNX_PRINT("%s:dev:0x%p, vif_index:%d, reason_code:%d \n", __func__, dev, ecrnx_vif->vif_index, reason_code);
1742
1743     return(ecrnx_send_sm_disconnect_req(ecrnx_hw, ecrnx_vif, reason_code));
1744 }
1745
1746 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
1747 /**
1748  * @external_auth: indicates result of offloaded authentication processing from
1749  *     user space
1750  */
1751 static int ecrnx_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *dev,
1752                                        struct cfg80211_external_auth_params *params)
1753 {
1754     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1755     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
1756
1757     if (!(ecrnx_vif->sta.flags & ECRNX_STA_EXT_AUTH))
1758         return -EINVAL;
1759
1760     ecrnx_external_auth_disable(ecrnx_vif);
1761     return ecrnx_send_sm_external_auth_required_rsp(ecrnx_hw, ecrnx_vif,
1762                                                    params->status);
1763 }
1764 #endif
1765
1766 /**
1767  * @add_station: Add a new station.
1768  */
1769 static int ecrnx_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
1770                                      const u8 *mac, struct station_parameters *params)
1771 {
1772     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1773     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
1774     struct me_sta_add_cfm me_sta_add_cfm;
1775     int error = 0;
1776
1777     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1778
1779     WARN_ON(ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_AP_VLAN);
1780
1781     /* Do not add TDLS station */
1782     if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
1783         return 0;
1784
1785     /* Indicate we are in a STA addition process - This will allow handling
1786      * potential PS mode change indications correctly
1787      */
1788     set_bit(ECRNX_DEV_ADDING_STA, &ecrnx_hw->flags);
1789
1790     /* Forward the information to the LMAC */
1791     if ((error = ecrnx_send_me_sta_add(ecrnx_hw, params, mac, ecrnx_vif->vif_index,
1792                                       &me_sta_add_cfm)))
1793         return error;
1794
1795     // Check the status
1796     switch (me_sta_add_cfm.status)
1797     {
1798         case CO_OK:
1799         {
1800             struct ecrnx_sta *sta = &ecrnx_hw->sta_table[me_sta_add_cfm.sta_idx];
1801
1802             ECRNX_PRINT("%s-%d:sta:0x%p, sta_idx:%d \n", __func__, __LINE__, sta, me_sta_add_cfm.sta_idx);
1803             int tid;
1804             sta->aid = params->aid;
1805             memset(sta->rx_pn, 0, TID_MAX * sizeof(uint64_t));
1806             sta->sta_idx = me_sta_add_cfm.sta_idx;
1807             sta->ch_idx = ecrnx_vif->ch_index;
1808             sta->vif_idx = ecrnx_vif->vif_index;
1809             sta->vlan_idx = sta->vif_idx;
1810             sta->qos = (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)) != 0;
1811             sta->ht = params->ht_capa ? 1 : 0;
1812             sta->vht = params->vht_capa ? 1 : 0;
1813             sta->acm = 0;
1814             sta->listen_interval = params->listen_interval;
1815 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
1816             if (params->local_pm != NL80211_MESH_POWER_UNKNOWN)
1817                 sta->mesh_pm = params->local_pm;
1818             else
1819                 sta->mesh_pm = ecrnx_vif->ap.next_mesh_pm;
1820 #endif
1821             ecrnx_update_mesh_power_mode(ecrnx_vif);
1822
1823             for (tid = 0; tid < NX_NB_TXQ_PER_STA; tid++) {
1824                 int uapsd_bit = ecrnx_hwq2uapsd[ecrnx_tid2hwq[tid]];
1825                 if (params->uapsd_queues & uapsd_bit)
1826                     sta->uapsd_tids |= 1 << tid;
1827                 else
1828                     sta->uapsd_tids &= ~(1 << tid);
1829             }
1830             memcpy(sta->mac_addr, mac, ETH_ALEN);
1831             ecrnx_dbgfs_register_sta(ecrnx_hw, sta);
1832
1833             /* Ensure that we won't process PS change or channel switch ind*/
1834             spin_lock_bh(&ecrnx_hw->cb_lock);
1835             ecrnx_txq_sta_init(ecrnx_hw, sta, ecrnx_txq_vif_get_status(ecrnx_vif));
1836             ecrnx_rx_reord_sta_init(ecrnx_hw, ecrnx_vif, sta->sta_idx);
1837             list_add_tail(&sta->list, &ecrnx_vif->ap.sta_list);
1838             ecrnx_vif->generation++;
1839             sta->valid = true;
1840             ecrnx_ps_bh_enable(ecrnx_hw, sta, sta->ps.active || me_sta_add_cfm.pm_state);
1841             spin_unlock_bh(&ecrnx_hw->cb_lock);
1842
1843 #ifdef CONFIG_ECRNX_ANDRIOD
1844             if((ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_AP) || (ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_P2P_GO)) {
1845                 struct station_info sinfo;
1846                 u8 ie_offset;
1847
1848                 if((!is_multicast_sta(sta->sta_idx)) && (sta->mac_addr)) {
1849                     memset(&sinfo, 0, sizeof(sinfo));
1850
1851 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
1852                     sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
1853 #endif
1854                     sinfo.assoc_req_ies = NULL;
1855                     sinfo.assoc_req_ies_len = 0;
1856                     ECRNX_PRINT("%s-%d:sta:0x%x,sta->mac_addr:%pM \n", __func__, __LINE__, sta, sta->mac_addr);
1857                     cfg80211_new_sta(ecrnx_vif->ndev, sta->mac_addr, &sinfo, GFP_ATOMIC);
1858                 }
1859             }
1860 #endif
1861
1862             error = 0;
1863
1864 #ifdef CONFIG_ECRNX_BFMER
1865             if (ecrnx_hw->mod_params->bfmer)
1866                 ecrnx_send_bfmer_enable(ecrnx_hw, sta, params->vht_capa);
1867
1868             ecrnx_mu_group_sta_init(sta, params->vht_capa);
1869 #endif /* CONFIG_ECRNX_BFMER */
1870
1871             #define PRINT_STA_FLAG(f)                               \
1872                 (params->sta_flags_set & BIT(NL80211_STA_FLAG_##f) ? "["#f"]" : "")
1873
1874 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
1875             netdev_info(dev, "Add sta %d (%pM) flags=%s%s%s%s%s%s%s",
1876                         sta->sta_idx, mac,
1877                         PRINT_STA_FLAG(AUTHORIZED),
1878                         PRINT_STA_FLAG(SHORT_PREAMBLE),
1879                         PRINT_STA_FLAG(WME),
1880                         PRINT_STA_FLAG(MFP),
1881                         PRINT_STA_FLAG(AUTHENTICATED),
1882                         PRINT_STA_FLAG(TDLS_PEER),
1883                         PRINT_STA_FLAG(ASSOCIATED));
1884 #else
1885             netdev_info(dev, "Add sta %d (%pM) flags=%s%s%s%s%s%s",
1886                         sta->sta_idx, mac,
1887                         PRINT_STA_FLAG(AUTHORIZED),
1888                         PRINT_STA_FLAG(SHORT_PREAMBLE),
1889                         PRINT_STA_FLAG(WME),
1890                         PRINT_STA_FLAG(MFP),
1891                         PRINT_STA_FLAG(AUTHENTICATED),
1892                         PRINT_STA_FLAG(TDLS_PEER));
1893 #endif
1894
1895             #undef PRINT_STA_FLAG
1896 #if defined(CONFIG_ECRNX_DEBUGFS_CUSTOM)
1897             ecrnx_debugfs_add_station_in_ap_mode(ecrnx_hw, sta, params);
1898 #endif
1899             break;
1900         }
1901         default:
1902             error = -EBUSY;
1903             break;
1904     }
1905
1906     clear_bit(ECRNX_DEV_ADDING_STA, &ecrnx_hw->flags);
1907
1908     return error;
1909 }
1910
1911 /**
1912  * @del_station: Remove a station
1913  */
1914 static int ecrnx_cfg80211_del_station(struct wiphy *wiphy,
1915                                         struct net_device *dev,
1916 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))
1917                                         u8 *mac
1918 #elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))
1919                                         const u8 *mac
1920 #else
1921                                         struct station_del_parameters *params
1922 #endif
1923 )
1924 {
1925     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1926     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
1927     struct ecrnx_sta *cur, *tmp;
1928     int error = 0, found = 0;
1929
1930 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
1931     const u8 *mac = NULL;
1932     if (params)
1933         mac = params->mac;
1934 #endif
1935
1936     if(list_empty(&ecrnx_vif->ap.sta_list)) {
1937         goto end;
1938     }
1939
1940     list_for_each_entry_safe(cur, tmp, &ecrnx_vif->ap.sta_list, list) {
1941         if ((!mac) || (!memcmp(cur->mac_addr, mac, ETH_ALEN))) {
1942             netdev_info(dev, "Del sta %d (%pM)", cur->sta_idx, cur->mac_addr);
1943             ECRNX_PRINT("%s-%d:cur_list:0x%p, vif_list:0x%p, mac:%pM\n", __func__, __LINE__, &cur->list, &ecrnx_vif->ap.sta_list, mac);
1944             /* Ensure that we won't process PS change ind */
1945             spin_lock_bh(&ecrnx_hw->cb_lock);
1946             cur->ps.active = false;
1947             cur->valid = false;
1948             spin_unlock_bh(&ecrnx_hw->cb_lock);
1949
1950             if (cur->vif_idx != cur->vlan_idx) {
1951                 struct ecrnx_vif *vlan_vif;
1952                 vlan_vif = ecrnx_hw->vif_table[cur->vlan_idx];
1953                 if (vlan_vif->up) {
1954                     if ((ECRNX_VIF_TYPE(vlan_vif) == NL80211_IFTYPE_AP_VLAN) &&
1955                         (vlan_vif->use_4addr)) {
1956                         vlan_vif->ap_vlan.sta_4a = NULL;
1957                     } else {
1958                         WARN(1, "Deleting sta belonging to VLAN other than AP_VLAN 4A");
1959                     }
1960                 }
1961             }
1962
1963             ecrnx_txq_sta_deinit(ecrnx_hw, cur);
1964             ecrnx_rx_reord_sta_deinit(ecrnx_hw, cur->sta_idx, true);
1965
1966             error = ecrnx_send_me_sta_del(ecrnx_hw, cur->sta_idx, false);
1967             if ((error != 0) && (error != -EPIPE)){
1968                 ECRNX_WARN("del sta msg send fail, error code:%d \n", error);
1969             }
1970
1971 #ifdef CONFIG_ECRNX_ANDRIOD
1972             if((ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_AP) || (ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_P2P_GO)) {
1973                 if((!is_multicast_sta(cur->sta_idx)) && params) {
1974                     if(params->mac){
1975                         ECRNX_PRINT("%s-%d:vif:%d, mac:%pM \n", __func__, __LINE__, ECRNX_VIF_TYPE(ecrnx_vif), params->mac);
1976                         cfg80211_del_sta(ecrnx_vif->ndev, params->mac, GFP_ATOMIC);
1977                     }
1978                 }
1979             }
1980 #endif
1981
1982
1983 #ifdef CONFIG_ECRNX_BFMER
1984             // Disable Beamformer if supported
1985             ecrnx_bfmer_report_del(ecrnx_hw, cur);
1986             ecrnx_mu_group_sta_del(ecrnx_hw, cur);
1987 #endif /* CONFIG_ECRNX_BFMER */
1988
1989             list_del(&cur->list);
1990             ecrnx_vif->generation++;
1991             ecrnx_dbgfs_unregister_sta(ecrnx_hw, cur);
1992 #if defined(CONFIG_ECRNX_DEBUGFS_CUSTOM)
1993             ecrnx_debugfs_sta_in_ap_del(cur->sta_idx);
1994 #endif
1995             found ++;
1996             break;
1997         }
1998     }
1999
2000 end:
2001     if ((!found) && (mac))
2002         return -ENOENT;
2003
2004     ecrnx_update_mesh_power_mode(ecrnx_vif);
2005
2006     return 0;
2007 }
2008
2009 /**
2010  * @change_station: Modify a given station. Note that flags changes are not much
2011  *      validated in cfg80211, in particular the auth/assoc/authorized flags
2012  *      might come to the driver in invalid combinations -- make sure to check
2013  *      them, also against the existing state! Drivers must call
2014  *      cfg80211_check_station_change() to validate the information.
2015  */
2016 static int ecrnx_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,
2017                                         const u8 *mac, struct station_parameters *params)
2018 {
2019     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2020     struct ecrnx_vif *vif = netdev_priv(dev);
2021     struct ecrnx_sta *sta;
2022
2023     sta = ecrnx_get_sta(ecrnx_hw, mac);
2024     if (!sta)
2025     {
2026         /* Add the TDLS station */
2027         if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
2028         {
2029             struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
2030             struct me_sta_add_cfm me_sta_add_cfm;
2031             int error = 0;
2032
2033             /* Indicate we are in a STA addition process - This will allow handling
2034              * potential PS mode change indications correctly
2035              */
2036             set_bit(ECRNX_DEV_ADDING_STA, &ecrnx_hw->flags);
2037
2038             /* Forward the information to the LMAC */
2039             if ((error = ecrnx_send_me_sta_add(ecrnx_hw, params, mac, ecrnx_vif->vif_index,
2040                                               &me_sta_add_cfm)))
2041                 return error;
2042
2043             // Check the status
2044             switch (me_sta_add_cfm.status)
2045             {
2046                 case CO_OK:
2047                 {
2048                     int tid;
2049                     sta = &ecrnx_hw->sta_table[me_sta_add_cfm.sta_idx];
2050                     memset(&sta->rx_pn, 0, TID_MAX * sizeof(uint64_t));
2051                     sta->aid = params->aid;
2052                     sta->sta_idx = me_sta_add_cfm.sta_idx;
2053                     sta->ch_idx = ecrnx_vif->ch_index;
2054                     sta->vif_idx = ecrnx_vif->vif_index;
2055                     sta->vlan_idx = sta->vif_idx;
2056                     sta->qos = (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)) != 0;
2057                     sta->ht = params->ht_capa ? 1 : 0;
2058                     sta->vht = params->vht_capa ? 1 : 0;
2059                     sta->acm = 0;
2060                     for (tid = 0; tid < NX_NB_TXQ_PER_STA; tid++) {
2061                         int uapsd_bit = ecrnx_hwq2uapsd[ecrnx_tid2hwq[tid]];
2062                         if (params->uapsd_queues & uapsd_bit)
2063                             sta->uapsd_tids |= 1 << tid;
2064                         else
2065                             sta->uapsd_tids &= ~(1 << tid);
2066                     }
2067                     memcpy(sta->mac_addr, mac, ETH_ALEN);
2068                     ecrnx_dbgfs_register_sta(ecrnx_hw, sta);
2069
2070                     /* Ensure that we won't process PS change or channel switch ind*/
2071                     spin_lock_bh(&ecrnx_hw->cb_lock);
2072                     ecrnx_txq_sta_init(ecrnx_hw, sta, ecrnx_txq_vif_get_status(ecrnx_vif));
2073                     ecrnx_rx_reord_sta_init(ecrnx_hw, ecrnx_vif, sta->sta_idx);
2074                     if (ecrnx_vif->tdls_status == TDLS_SETUP_RSP_TX) {
2075                         ecrnx_vif->tdls_status = TDLS_LINK_ACTIVE;
2076                         sta->tdls.initiator = true;
2077                         sta->tdls.active = true;
2078                     }
2079                     /* Set TDLS channel switch capability */
2080 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
2081                     if ((params->ext_capab[3] & WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) &&
2082                         !ecrnx_vif->tdls_chsw_prohibited)
2083 #else
2084                     if (!ecrnx_vif->tdls_chsw_prohibited)
2085 #endif
2086                         sta->tdls.chsw_allowed = true;
2087                     ecrnx_vif->sta.tdls_sta = sta;
2088                     sta->valid = true;
2089                     spin_unlock_bh(&ecrnx_hw->cb_lock);
2090 #ifdef CONFIG_ECRNX_BFMER
2091                     if (ecrnx_hw->mod_params->bfmer)
2092                         ecrnx_send_bfmer_enable(ecrnx_hw, sta, params->vht_capa);
2093
2094                     ecrnx_mu_group_sta_init(sta, NULL);
2095 #endif /* CONFIG_ECRNX_BFMER */
2096
2097                     #define PRINT_STA_FLAG(f)                               \
2098                         (params->sta_flags_set & BIT(NL80211_STA_FLAG_##f) ? "["#f"]" : "")
2099
2100 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
2101                     netdev_info(dev, "Add %s TDLS sta %d (%pM) flags=%s%s%s%s%s%s%s",
2102                                 sta->tdls.initiator ? "initiator" : "responder",
2103                                 sta->sta_idx, mac,
2104                                 PRINT_STA_FLAG(AUTHORIZED),
2105                                 PRINT_STA_FLAG(SHORT_PREAMBLE),
2106                                 PRINT_STA_FLAG(WME),
2107                                 PRINT_STA_FLAG(MFP),
2108                                 PRINT_STA_FLAG(AUTHENTICATED),
2109                                 PRINT_STA_FLAG(TDLS_PEER),
2110                                 PRINT_STA_FLAG(ASSOCIATED));
2111 #else
2112                     netdev_info(dev, "Add %s TDLS sta %d (%pM) flags=%s%s%s%s%s%s",
2113                             sta->tdls.initiator ? "initiator" : "responder",
2114                             sta->sta_idx, mac,
2115                             PRINT_STA_FLAG(AUTHORIZED),
2116                             PRINT_STA_FLAG(SHORT_PREAMBLE),
2117                             PRINT_STA_FLAG(WME),
2118                             PRINT_STA_FLAG(MFP),
2119                             PRINT_STA_FLAG(AUTHENTICATED),
2120                             PRINT_STA_FLAG(TDLS_PEER));
2121 #endif
2122                     #undef PRINT_STA_FLAG
2123
2124                     break;
2125                 }
2126                 default:
2127                     error = -EBUSY;
2128                     break;
2129             }
2130
2131             clear_bit(ECRNX_DEV_ADDING_STA, &ecrnx_hw->flags);
2132         } else  {
2133             return -EINVAL;
2134         }
2135     }
2136
2137     if (params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))
2138         ecrnx_send_me_set_control_port_req(ecrnx_hw,
2139                 (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) != 0,
2140                 sta->sta_idx);
2141
2142 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
2143     if (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_MESH_POINT) {
2144         if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) {
2145             if (params->plink_state < NUM_NL80211_PLINK_STATES) {
2146                 ecrnx_send_mesh_peer_update_ntf(ecrnx_hw, vif, sta->sta_idx, params->plink_state);
2147             }
2148         }
2149
2150         if (params->local_pm != NL80211_MESH_POWER_UNKNOWN) {
2151             sta->mesh_pm = params->local_pm;
2152             ecrnx_update_mesh_power_mode(vif);
2153         }
2154     }
2155 #endif
2156
2157     if (params->vlan) {
2158         uint8_t vlan_idx;
2159
2160         vif = netdev_priv(params->vlan);
2161         vlan_idx = vif->vif_index;
2162
2163         if (sta->vlan_idx != vlan_idx) {
2164             struct ecrnx_vif *old_vif;
2165             old_vif = ecrnx_hw->vif_table[sta->vlan_idx];
2166             ecrnx_txq_sta_switch_vif(sta, old_vif, vif);
2167             sta->vlan_idx = vlan_idx;
2168
2169             if ((ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_AP_VLAN) &&
2170                 (vif->use_4addr)) {
2171                 WARN((vif->ap_vlan.sta_4a),
2172                      "4A AP_VLAN interface with more than one sta");
2173                 vif->ap_vlan.sta_4a = sta;
2174             }
2175
2176             if ((ECRNX_VIF_TYPE(old_vif) == NL80211_IFTYPE_AP_VLAN) &&
2177                 (old_vif->use_4addr)) {
2178                 old_vif->ap_vlan.sta_4a = NULL;
2179             }
2180         }
2181     }
2182
2183     return 0;
2184 }
2185
2186 /**
2187  * @start_ap: Start acting in AP mode defined by the parameters.
2188  */
2189 static int ecrnx_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
2190                                   struct cfg80211_ap_settings *settings)
2191 {
2192     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2193     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
2194     struct apm_start_cfm apm_start_cfm;
2195     struct ecrnx_ipc_elem_var elem;
2196     struct ecrnx_sta *sta;
2197     int error = 0;
2198
2199     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2200
2201     /* Forward the information to the LMAC */
2202     if ((error = ecrnx_send_apm_start_req(ecrnx_hw, ecrnx_vif, settings,
2203                                          &apm_start_cfm, &elem)))
2204         goto end;
2205
2206     // Check the status
2207     switch (apm_start_cfm.status)
2208     {
2209         case CO_OK:
2210         {
2211             u8 txq_status = 0;
2212             ecrnx_vif->ap.bcmc_index = apm_start_cfm.bcmc_idx;
2213             ecrnx_vif->ap.flags = 0;
2214             ecrnx_vif->ap.bcn_interval = settings->beacon_interval;
2215             sta = &ecrnx_hw->sta_table[apm_start_cfm.bcmc_idx];
2216             sta->valid = true;
2217             sta->aid = 0;
2218             sta->sta_idx = apm_start_cfm.bcmc_idx;
2219             sta->ch_idx = apm_start_cfm.ch_idx;
2220             sta->vif_idx = ecrnx_vif->vif_index;
2221             sta->qos = false;
2222             sta->acm = 0;
2223             sta->ps.active = false;
2224             sta->listen_interval = 5;
2225             ecrnx_mu_group_sta_init(sta, NULL);
2226             spin_lock_bh(&ecrnx_hw->cb_lock);
2227             ecrnx_chanctx_link(ecrnx_vif, apm_start_cfm.ch_idx,
2228                               &settings->chandef);
2229             if (ecrnx_hw->cur_chanctx != apm_start_cfm.ch_idx) {
2230                 txq_status = ECRNX_TXQ_STOP_CHAN;
2231             }
2232             ecrnx_txq_vif_init(ecrnx_hw, ecrnx_vif, txq_status);
2233             spin_unlock_bh(&ecrnx_hw->cb_lock);
2234
2235             netif_tx_start_all_queues(dev);
2236             netif_carrier_on(dev);
2237             error = 0;
2238             /* If the AP channel is already the active, we probably skip radar
2239                activation on MM_CHANNEL_SWITCH_IND (unless another vif use this
2240                ctxt). In anycase retest if radar detection must be activated
2241              */
2242             if (txq_status == 0) {
2243                 ecrnx_radar_detection_enable_on_cur_channel(ecrnx_hw);
2244             }
2245             break;
2246         }
2247         case CO_BUSY:
2248             error = -EINPROGRESS;
2249             break;
2250         case CO_OP_IN_PROGRESS:
2251             error = -EALREADY;
2252             break;
2253         default:
2254             error = -EIO;
2255             break;
2256     }
2257
2258     if (error) {
2259         netdev_info(dev, "Failed to start AP (%d)", error);
2260     } else {
2261         netdev_info(dev, "AP started: ch=%d, bcmc_idx=%d",
2262                     ecrnx_vif->ch_index, ecrnx_vif->ap.bcmc_index);
2263     }
2264
2265   end:
2266     ecrnx_ipc_elem_var_deallocs(ecrnx_hw, &elem);
2267
2268     return error;
2269 }
2270
2271
2272 /**
2273  * @change_beacon: Change the beacon parameters for an access point mode
2274  *      interface. This should reject the call when AP mode wasn't started.
2275  */
2276 static int ecrnx_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
2277                                        struct cfg80211_beacon_data *info)
2278 {
2279     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2280     struct ecrnx_vif *vif = netdev_priv(dev);
2281     struct ecrnx_bcn *bcn = &vif->ap.bcn;
2282     struct ecrnx_ipc_elem_var elem;
2283     u8 *buf;
2284     int error = 0;
2285
2286     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2287
2288     // Build the beacon
2289     buf = ecrnx_build_bcn(bcn, info);
2290     if (!buf)
2291         return -ENOMEM;
2292
2293     // Sync buffer for FW
2294     if ((error = ecrnx_ipc_elem_var_allocs(ecrnx_hw, &elem, bcn->len, DMA_TO_DEVICE,
2295                                           buf, NULL, NULL)))
2296         return error;
2297
2298     // Forward the information to the LMAC
2299     error = ecrnx_send_bcn_change(ecrnx_hw, vif->vif_index, elem.dma_addr,
2300                                  bcn->len, bcn->head_len, bcn->tim_len, NULL);
2301
2302     ecrnx_ipc_elem_var_deallocs(ecrnx_hw, &elem);
2303
2304     return error;
2305 }
2306
2307 /**
2308  * * @stop_ap: Stop being an AP, including stopping beaconing.
2309  */
2310 static int ecrnx_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
2311 {
2312     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2313     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
2314     struct ecrnx_sta *sta;
2315
2316     ecrnx_radar_cancel_cac(&ecrnx_hw->radar);
2317     ecrnx_send_apm_stop_req(ecrnx_hw, ecrnx_vif);
2318     spin_lock_bh(&ecrnx_hw->cb_lock);
2319     ecrnx_chanctx_unlink(ecrnx_vif);
2320     spin_unlock_bh(&ecrnx_hw->cb_lock);
2321
2322     /* delete any remaining STA*/
2323     while (!list_empty(&ecrnx_vif->ap.sta_list)) {
2324         ecrnx_cfg80211_del_station(wiphy, dev, NULL);
2325     }
2326
2327     /* delete BC/MC STA */
2328     sta = &ecrnx_hw->sta_table[ecrnx_vif->ap.bcmc_index];
2329     ecrnx_txq_vif_deinit(ecrnx_hw, ecrnx_vif);
2330     ecrnx_del_bcn(&ecrnx_vif->ap.bcn);
2331     ecrnx_del_csa(ecrnx_vif);
2332
2333     netif_tx_stop_all_queues(dev);
2334     netif_carrier_off(dev);
2335
2336     netdev_info(dev, "AP Stopped");
2337
2338     return 0;
2339 }
2340
2341 /**
2342  * @set_monitor_channel: Set the monitor mode channel for the device. If other
2343  *      interfaces are active this callback should reject the configuration.
2344  *      If no interfaces are active or the device is down, the channel should
2345  *      be stored for when a monitor interface becomes active.
2346  *
2347  * Also called internaly with chandef set to NULL simply to retrieve the channel
2348  * configured at firmware level.
2349  */
2350 static int ecrnx_cfg80211_set_monitor_channel(struct wiphy *wiphy,
2351                                              struct cfg80211_chan_def *chandef)
2352 {
2353     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2354     struct ecrnx_vif *ecrnx_vif;
2355     struct me_config_monitor_cfm cfm;
2356     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2357
2358     if (ecrnx_hw->monitor_vif == ECRNX_INVALID_VIF)
2359         return -EINVAL;
2360
2361     ecrnx_vif = ecrnx_hw->vif_table[ecrnx_hw->monitor_vif];
2362
2363     // Do nothing if monitor interface is already configured with the requested channel
2364     if (ecrnx_chanctx_valid(ecrnx_hw, ecrnx_vif->ch_index)) {
2365         struct ecrnx_chanctx *ctxt;
2366         ctxt = &ecrnx_vif->ecrnx_hw->chanctx_table[ecrnx_vif->ch_index];
2367         if (chandef && cfg80211_chandef_identical(&ctxt->chan_def, chandef))
2368             return 0;
2369     }
2370
2371     // Always send command to firmware. It allows to retrieve channel context index
2372     // and its configuration.
2373     if (ecrnx_send_config_monitor_req(ecrnx_hw, chandef, &cfm))
2374         return -EIO;
2375
2376     // Always re-set channel context info
2377     ecrnx_chanctx_unlink(ecrnx_vif);
2378
2379
2380
2381     // If there is also a STA interface not yet connected then monitor interface
2382     // will only have a channel context after the connection of the STA interface.
2383     if (cfm.chan_index != ECRNX_CH_NOT_SET)
2384     {
2385         struct cfg80211_chan_def mon_chandef;
2386
2387         if (ecrnx_hw->vif_started > 1) {
2388             // In this case we just want to update the channel context index not
2389             // the channel configuration
2390             ecrnx_chanctx_link(ecrnx_vif, cfm.chan_index, NULL);
2391             return -EBUSY;
2392         }
2393
2394         mon_chandef.chan = ieee80211_get_channel(wiphy, cfm.chan.prim20_freq);
2395         mon_chandef.center_freq1 = cfm.chan.center1_freq;
2396         mon_chandef.center_freq2 = cfm.chan.center2_freq;
2397         mon_chandef.width =  chnl2bw[cfm.chan.type];
2398         ecrnx_chanctx_link(ecrnx_vif, cfm.chan_index, &mon_chandef);
2399     }
2400
2401     return 0;
2402 }
2403
2404 /**
2405  * @probe_client: probe an associated client, must return a cookie that it
2406  *      later passes to cfg80211_probe_status().
2407  */
2408 int ecrnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
2409             const u8 *peer, u64 *cookie)
2410 {
2411     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2412     struct ecrnx_vif *vif = netdev_priv(dev);
2413     struct ecrnx_sta *sta = NULL;
2414     struct apm_probe_client_cfm cfm;
2415     if ((ECRNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP) &&
2416         (ECRNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP_VLAN) &&
2417         (ECRNX_VIF_TYPE(vif) != NL80211_IFTYPE_P2P_GO) &&
2418         (ECRNX_VIF_TYPE(vif) != NL80211_IFTYPE_MESH_POINT))
2419         return -EINVAL;
2420     list_for_each_entry(sta, &vif->ap.sta_list, list) {
2421         if (sta->valid && ether_addr_equal(sta->mac_addr, peer))
2422             break;
2423 }
2424
2425     if (!sta)
2426         return -EINVAL;
2427
2428     ecrnx_send_apm_probe_req(ecrnx_hw, vif, sta, &cfm);
2429
2430     if (cfm.status != CO_OK)
2431         return -EINVAL;
2432
2433     *cookie = (u64)cfm.probe_id;
2434     return 0;
2435 }
2436
2437 /**
2438  * @set_wiphy_params: Notify that wiphy parameters have changed;
2439  *      @changed bitfield (see &enum wiphy_params_flags) describes which values
2440  *      have changed. The actual parameter values are available in
2441  *      struct wiphy. If returning an error, no value should be changed.
2442  */
2443 static int ecrnx_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
2444 {
2445     return 0;
2446 }
2447
2448
2449 /**
2450  * @set_tx_power: set the transmit power according to the parameters,
2451  *      the power passed is in mBm, to get dBm use MBM_TO_DBM(). The
2452  *      wdev may be %NULL if power was set for the wiphy, and will
2453  *      always be %NULL unless the driver supports per-vif TX power
2454  *      (as advertised by the nl80211 feature flag.)
2455  */
2456 static int ecrnx_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
2457                                       enum nl80211_tx_power_setting type, int mbm)
2458 {
2459     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2460     struct ecrnx_vif *vif;
2461     s8 pwr;
2462     int res = 0;
2463
2464     if (type == NL80211_TX_POWER_AUTOMATIC) {
2465         pwr = 0x7f;
2466     } else {
2467         pwr = MBM_TO_DBM(mbm);
2468     }
2469
2470     if (wdev) {
2471         vif = container_of(wdev, struct ecrnx_vif, wdev);
2472         res = ecrnx_send_set_power(ecrnx_hw, vif->vif_index, pwr, NULL);
2473     } else {
2474         list_for_each_entry(vif, &ecrnx_hw->vifs, list) {
2475             res = ecrnx_send_set_power(ecrnx_hw, vif->vif_index, pwr, NULL);
2476             if (res)
2477                 break;
2478         }
2479     }
2480
2481     return res;
2482 }
2483
2484 /**
2485  * @set_power_mgmt: set the power save to one of those two modes:
2486  *  Power-save off
2487  *  Power-save on - Dynamic mode
2488  */
2489 static int ecrnx_cfg80211_set_power_mgmt(struct wiphy *wiphy,
2490                                         struct net_device *dev,
2491                                         bool enabled, int timeout)
2492 {
2493     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2494     u8 ps_mode;
2495
2496     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2497     if (timeout >= 0)
2498         netdev_info(dev, "Ignore timeout value %d", timeout);
2499
2500     if (!(ecrnx_hw->version_cfm.features & BIT(MM_FEAT_PS_BIT)))
2501         enabled = false;
2502
2503     if (enabled) {
2504         /* Switch to Dynamic Power Save */
2505         ps_mode = MM_PS_MODE_ON_DYN;
2506     } else {
2507         /* Exit Power Save */
2508         ps_mode = MM_PS_MODE_OFF;
2509     }
2510
2511     return ecrnx_send_me_set_ps_mode(ecrnx_hw, ps_mode);
2512 }
2513
2514 static int ecrnx_cfg80211_set_txq_params(struct wiphy *wiphy, struct net_device *dev,
2515                                         struct ieee80211_txq_params *params)
2516 {
2517     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2518     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
2519     u8 hw_queue, aifs, cwmin, cwmax;
2520     u32 param;
2521
2522     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2523
2524     hw_queue = ecrnx_ac2hwq[0][params->ac];
2525
2526     aifs  = params->aifs;
2527     cwmin = fls(params->cwmin);
2528     cwmax = fls(params->cwmax);
2529
2530     /* Store queue information in general structure */
2531     param  = (u32) (aifs << 0);
2532     param |= (u32) (cwmin << 4);
2533     param |= (u32) (cwmax << 8);
2534     param |= (u32) (params->txop) << 12;
2535
2536     /* Send the MM_SET_EDCA_REQ message to the FW */
2537     return ecrnx_send_set_edca(ecrnx_hw, hw_queue, param, false, ecrnx_vif->vif_index);
2538 }
2539
2540
2541 /**
2542  * @remain_on_channel: Request the driver to remain awake on the specified
2543  *      channel for the specified duration to complete an off-channel
2544  *      operation (e.g., public action frame exchange). When the driver is
2545  *      ready on the requested channel, it must indicate this with an event
2546  *      notification by calling cfg80211_ready_on_channel().
2547  */
2548 static int
2549 ecrnx_cfg80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
2550                                 struct ieee80211_channel *chan,
2551                                 unsigned int duration, u64 *cookie)
2552 {
2553     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2554     struct ecrnx_vif *ecrnx_vif = netdev_priv(wdev->netdev);
2555     struct ecrnx_roc *roc;
2556     int error;
2557     unsigned long timer = 0;
2558
2559     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2560
2561     /* For debug purpose (use ftrace kernel option) */
2562     trace_roc(ecrnx_vif->vif_index, chan->center_freq, duration);
2563
2564     /* Check that no other RoC procedure has been launched */
2565     if (ecrnx_hw->roc)
2566     {
2567         ECRNX_ERR("%s-%d,statu error!!!, duration:%d \n", __func__, __LINE__, duration);
2568         //exp_report(ecrnx_hw);
2569             //wait for slave confirm
2570         //ecrnx_hw->p2p_listen.rxdatas = 0;
2571 #ifdef CONFIG_ECRNX_P2P
2572                 timer = wait_event_interruptible_timeout(ecrnx_hw->p2p_listen.rxdataq, (ecrnx_hw->roc == NULL), HZ/2);
2573                 if (timer)
2574                         ECRNX_PRINT("wait_event: wake up!!! timer:%ld \n", timer);
2575                 else
2576                         ECRNX_PRINT("wait_event: timout!!!\n");
2577 #endif
2578         //return -EBUSY;
2579     }
2580
2581     /* Allocate a temporary RoC element */
2582     roc = kmalloc(sizeof(struct ecrnx_roc), GFP_KERNEL);
2583
2584     /* Verify that element has well been allocated */
2585     if (!roc)
2586         return -ENOMEM;
2587
2588     /* Initialize the RoC information element */
2589     roc->vif = ecrnx_vif;
2590     roc->chan = chan;
2591     roc->duration = duration;
2592     roc->internal = false;
2593     roc->on_chan = false;
2594
2595     /* Initialize the OFFCHAN TX queue to allow off-channel transmissions */
2596     ecrnx_txq_offchan_init(ecrnx_vif);
2597
2598     /* Forward the information to the FMAC */
2599     ecrnx_hw->roc = roc;
2600     error = ecrnx_send_roc(ecrnx_hw, ecrnx_vif, chan, duration);
2601
2602     /* If no error, keep all the information for handling of end of procedure */
2603     if (error == 0) {
2604
2605         /* Set the cookie value */
2606         *cookie = (u64)(ecrnx_hw->roc_cookie);
2607
2608 #ifdef CONFIG_ECRNX_P2P
2609                 if(ecrnx_vif->mgmt_reg_stypes & BIT(IEEE80211_STYPE_PROBE_REQ >> 4))
2610                 {
2611                         if(ecrnx_send_p2p_start_listen_req(ecrnx_hw, ecrnx_vif, duration))
2612                                 ECRNX_ERR("P2P: start_listen failed\n");
2613                 }
2614 #endif
2615     } else {
2616         kfree(roc);
2617         ecrnx_hw->roc = NULL;
2618         ecrnx_txq_offchan_deinit(ecrnx_vif);
2619     }
2620
2621     return error;
2622 }
2623
2624 /**
2625  * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation.
2626  *      This allows the operation to be terminated prior to timeout based on
2627  *      the duration value.
2628  */
2629 static int ecrnx_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
2630                                                   struct wireless_dev *wdev,
2631                                                   u64 cookie)
2632 {
2633     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2634     struct ecrnx_vif *ecrnx_vif = netdev_priv(wdev->netdev);
2635         int error;
2636
2637     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2638
2639     /* For debug purpose (use ftrace kernel option) */
2640     trace_cancel_roc(ecrnx_vif->vif_index);
2641
2642     /* Check if a RoC procedure is pending */
2643     if (!ecrnx_hw->roc)
2644         return 0;
2645 #ifdef CONFIG_ECRNX_P2P
2646         //if(ecrnx_vif->mgmt_reg_stypes & BIT(IEEE80211_STYPE_PROBE_REQ >> 4))
2647         {
2648                 error = ecrnx_send_p2p_cancel_listen_req(ecrnx_hw, ecrnx_vif);
2649                 if(error == 0)
2650                         ECRNX_PRINT("P2P: cancel_listen OK!!!\n");
2651                 else
2652                         ECRNX_ERR("P2P: cancel_listen failed, error=%d\n", error);
2653         }
2654 #endif
2655     /* Forward the information to the FMAC */
2656     return ecrnx_send_cancel_roc(ecrnx_hw);
2657 }
2658
2659 /**
2660  * @dump_survey: get site survey information.
2661  */
2662 static int ecrnx_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *netdev,
2663                                      int idx, struct survey_info *info)
2664 {
2665     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2666     struct ieee80211_supported_band *sband;
2667     struct ecrnx_survey_info *ecrnx_survey;
2668
2669     //ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2670
2671     if (idx >= ARRAY_SIZE(ecrnx_hw->survey))
2672         return -ENOENT;
2673
2674     ecrnx_survey = &ecrnx_hw->survey[idx];
2675
2676     // Check if provided index matches with a supported 2.4GHz channel
2677     sband = wiphy->bands[NL80211_BAND_2GHZ];
2678     if (sband && idx >= sband->n_channels) {
2679         idx -= sband->n_channels;
2680         sband = NULL;
2681     }
2682
2683     if (!sband) {
2684 #ifdef CONFIG_ECRNX_5G
2685         // Check if provided index matches with a supported 5GHz channel
2686         sband = wiphy->bands[NL80211_BAND_5GHZ];
2687 #endif
2688         if (!sband || idx >= sband->n_channels)
2689             return -ENOENT;
2690     }
2691
2692     // Fill the survey
2693     info->channel = &sband->channels[idx];
2694     info->filled = ecrnx_survey->filled;
2695
2696     if (ecrnx_survey->filled != 0) {
2697         SURVEY_TIME(info) = (u64)ecrnx_survey->chan_time_ms;
2698         SURVEY_TIME(info) = (u64)ecrnx_survey->chan_time_busy_ms;
2699         info->noise = ecrnx_survey->noise_dbm;
2700
2701         // Set the survey report as not used
2702         ecrnx_survey->filled = 0;
2703     }
2704
2705     return 0;
2706 }
2707
2708 /**
2709  * @get_channel: Get the current operating channel for the virtual interface.
2710  *      For monitor interfaces, it should return %NULL unless there's a single
2711  *      current monitoring channel.
2712  */
2713 int ecrnx_cfg80211_get_channel(struct wiphy *wiphy,
2714                                      struct wireless_dev *wdev,
2715                                      struct cfg80211_chan_def *chandef) {
2716     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2717     struct ecrnx_vif *ecrnx_vif = container_of(wdev, struct ecrnx_vif, wdev);
2718     struct ecrnx_chanctx *ctxt;
2719
2720     if (!ecrnx_vif->up) {
2721         return -ENODATA;
2722     }
2723
2724     if (ecrnx_vif->vif_index == ecrnx_hw->monitor_vif)
2725     {
2726         //retrieve channel from firmware
2727         ecrnx_cfg80211_set_monitor_channel(wiphy, NULL);
2728     }
2729
2730     //Check if channel context is valid
2731     if(!ecrnx_chanctx_valid(ecrnx_hw, ecrnx_vif->ch_index)){
2732         return -ENODATA;
2733     }
2734
2735     ctxt = &ecrnx_hw->chanctx_table[ecrnx_vif->ch_index];
2736     *chandef = ctxt->chan_def;
2737
2738     return 0;
2739 }
2740
2741 /**
2742  * @mgmt_tx: Transmit a management frame.
2743  */
2744 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2745 static int ecrnx_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
2746                                  struct cfg80211_mgmt_tx_params *params,
2747                                  u64 *cookie)
2748 #else
2749 static int ecrnx_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
2750                                  struct ieee80211_channel *channel, bool offchan,
2751                                  unsigned int wait, const u8* buf, size_t len,
2752                             #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
2753                                  bool no_cck,
2754                             #endif
2755                             #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
2756                                  bool dont_wait_for_ack,
2757                             #endif
2758                                  u64 *cookie)
2759 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
2760 {
2761     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2762     struct ecrnx_vif *ecrnx_vif = netdev_priv(wdev->netdev);
2763     struct ecrnx_sta *ecrnx_sta;
2764 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2765     struct ieee80211_channel *channel = params->chan;
2766     const u8 *buf = params->buf;
2767     bool offchan = false;
2768 #endif
2769     struct ieee80211_mgmt *mgmt = (void *)buf;
2770     bool ap = false;
2771
2772     /* Check if provided VIF is an AP or a STA one */
2773     switch (ECRNX_VIF_TYPE(ecrnx_vif)) {
2774         case NL80211_IFTYPE_AP_VLAN:
2775             ecrnx_vif = ecrnx_vif->ap_vlan.master;
2776             break;
2777         case NL80211_IFTYPE_AP:
2778         case NL80211_IFTYPE_P2P_GO:
2779         case NL80211_IFTYPE_MESH_POINT:
2780             ap = true;
2781             break;
2782         case NL80211_IFTYPE_STATION:
2783         case NL80211_IFTYPE_P2P_CLIENT:
2784         default:
2785             break;
2786     }
2787
2788     /* Get STA on which management frame has to be sent */
2789     ecrnx_sta = ecrnx_retrieve_sta(ecrnx_hw, ecrnx_vif, mgmt->da,
2790                                  mgmt->frame_control, ap);
2791
2792     trace_mgmt_tx((channel) ? channel->center_freq : 0,
2793                   ecrnx_vif->vif_index, (ecrnx_sta) ? ecrnx_sta->sta_idx : 0xFF,
2794                   mgmt);
2795
2796     if (ap || ecrnx_sta)
2797         goto send_frame;
2798
2799     /* Not an AP interface sending frame to unknown STA:
2800      * This is allowed for external authetication */
2801     if ((ecrnx_vif->sta.flags & ECRNX_STA_EXT_AUTH) && ieee80211_is_auth(mgmt->frame_control))
2802         goto send_frame;
2803
2804         if(ieee80211_is_probe_resp(mgmt->frame_control))
2805                 goto p2p_send_frame;
2806
2807     /* Otherwise ROC is needed */
2808     if (!channel)
2809         return -EINVAL;
2810
2811     /* Check that a RoC is already pending */
2812     if (ecrnx_hw->roc) {
2813         /* Get VIF used for current ROC */
2814
2815         /* Check if RoC channel is the same than the required one */
2816         if ((ecrnx_hw->roc->vif != ecrnx_vif) ||
2817             (ecrnx_hw->roc->chan->center_freq != channel->center_freq))
2818             return -EINVAL;
2819
2820     } else {
2821         u64 cookie;
2822         int error;
2823
2824         /* Start a ROC procedure for 30ms */
2825         error = ecrnx_cfg80211_remain_on_channel(wiphy, wdev, channel,
2826                                                 30, &cookie);
2827         if (error)
2828             return error;
2829
2830         /* Need to keep in mind that RoC has been launched internally in order to
2831          * avoid to call the cfg80211 callback once expired */
2832         ecrnx_hw->roc->internal = true;
2833 #ifdef CONFIG_ECRNX_P2P
2834                 ecrnx_hw->p2p_listen.rxdatas = 0;
2835                 wait_event_interruptible_timeout(ecrnx_hw->p2p_listen.rxdataq, ecrnx_hw->p2p_listen.rxdatas, HZ);
2836 #endif
2837     }
2838
2839 p2p_send_frame:
2840 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2841     offchan = true;
2842 #endif
2843
2844 send_frame:
2845 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2846     return ecrnx_start_mgmt_xmit(ecrnx_vif, ecrnx_sta, params, offchan, cookie);
2847 #else
2848     return ecrnx_start_mgmt_xmit(ecrnx_vif, ecrnx_sta, channel, offchan, wait, buf, len, no_cck, dont_wait_for_ack, cookie);
2849 #endif
2850 }
2851
2852 /**
2853  * @start_radar_detection: Start radar detection in the driver.
2854  */
2855 static int ecrnx_cfg80211_start_radar_detection(struct wiphy *wiphy,
2856                                         struct net_device *dev,
2857                                         struct cfg80211_chan_def *chandef,
2858                                         u32 cac_time_ms)
2859 {
2860     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2861     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
2862     struct apm_start_cac_cfm cfm;
2863
2864 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
2865     ecrnx_radar_start_cac(&ecrnx_hw->radar, cac_time_ms, ecrnx_vif);
2866 #endif
2867     ecrnx_send_apm_start_cac_req(ecrnx_hw, ecrnx_vif, chandef, &cfm);
2868
2869     if (cfm.status == CO_OK) {
2870         spin_lock_bh(&ecrnx_hw->cb_lock);
2871         ecrnx_chanctx_link(ecrnx_vif, cfm.ch_idx, chandef);
2872         if (ecrnx_hw->cur_chanctx == ecrnx_vif->ch_index)
2873             ecrnx_radar_detection_enable(&ecrnx_hw->radar,
2874                                         ECRNX_RADAR_DETECT_REPORT,
2875                                         ECRNX_RADAR_RIU);
2876         spin_unlock_bh(&ecrnx_hw->cb_lock);
2877     } else {
2878         return -EIO;
2879     }
2880
2881     return 0;
2882 }
2883
2884 /**
2885  * @update_ft_ies: Provide updated Fast BSS Transition information to the
2886  *      driver. If the SME is in the driver/firmware, this information can be
2887  *      used in building Authentication and Reassociation Request frames.
2888  */
2889 static int ecrnx_cfg80211_update_ft_ies(struct wiphy *wiphy,
2890                             struct net_device *dev,
2891                             struct cfg80211_update_ft_ies_params *ftie)
2892 {
2893     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2894     struct ecrnx_vif *vif = netdev_priv(dev);
2895     const struct ecrnx_element *rsne = NULL, *mde = NULL, *fte = NULL, *elem;
2896     bool ft_in_non_rsn = false;
2897     int fties_len = 0;
2898     u8 *ft_assoc_ies, *pos;
2899     if ((ECRNX_VIF_TYPE(vif) != NL80211_IFTYPE_STATION) ||
2900         (vif->sta.ft_assoc_ies == NULL))
2901         return 0;
2902     for_each_ecrnx_element(elem, ftie->ie, ftie->ie_len) {
2903         if (elem->id == WLAN_EID_RSN)
2904             rsne = elem;
2905         else if (elem->id == WLAN_EID_MOBILITY_DOMAIN)
2906             mde = elem;
2907         else if (elem->id == WLAN_EID_FAST_BSS_TRANSITION)
2908             fte = elem;
2909         else
2910             netdev_warn(dev, "Unexpected FT element %d\n", elem->id);
2911     }
2912     if (!mde) {
2913         netdev_warn(dev, "Didn't find Mobility_Domain Element\n");
2914         return 0;
2915     } else if (!rsne && !fte) {
2916         ft_in_non_rsn = true;
2917     } else if (!rsne || !fte) {
2918         netdev_warn(dev, "Didn't find RSN or Fast Transition Element\n");
2919         return 0;
2920     }
2921     for_each_ecrnx_element(elem, vif->sta.ft_assoc_ies, vif->sta.ft_assoc_ies_len) {
2922         if ((elem->id == WLAN_EID_RSN) ||
2923             (elem->id == WLAN_EID_MOBILITY_DOMAIN) ||
2924             (elem->id == WLAN_EID_FAST_BSS_TRANSITION))
2925             fties_len += elem->datalen + sizeof(struct ecrnx_element);
2926     }
2927     ft_assoc_ies = kmalloc(vif->sta.ft_assoc_ies_len - fties_len + ftie->ie_len,
2928                         GFP_KERNEL);
2929     if (!ft_assoc_ies) {
2930         netdev_warn(dev, "Fail to allocate buffer for association elements");
2931     }
2932     pos = ft_assoc_ies;
2933     for_each_ecrnx_element(elem, vif->sta.ft_assoc_ies, vif->sta.ft_assoc_ies_len) {
2934         if (elem->id == WLAN_EID_RSN) {
2935             if (ft_in_non_rsn) {
2936                 netdev_warn(dev, "Found RSN element in non RSN FT");
2937                 goto abort;
2938             } else if (!rsne) {
2939                 netdev_warn(dev, "Found several RSN element");
2940                 goto abort;
2941             } else {
2942                 memcpy(pos, rsne, sizeof(*rsne) + rsne->datalen);
2943                 pos += sizeof(*rsne) + rsne->datalen;
2944                 rsne = NULL;
2945             }
2946         } else if (elem->id == WLAN_EID_MOBILITY_DOMAIN) {
2947             if (!mde) {
2948                 netdev_warn(dev, "Found several Mobility Domain element");
2949                 goto abort;
2950             } else {
2951                 memcpy(pos, mde, sizeof(*mde) + mde->datalen);
2952                 pos += sizeof(*mde) + mde->datalen;
2953                 mde = NULL;
2954             }
2955         }
2956         else if (elem->id == WLAN_EID_FAST_BSS_TRANSITION) {
2957             if (ft_in_non_rsn) {
2958                 netdev_warn(dev, "Found Fast Transition element in non RSN FT");
2959                 goto abort;
2960             } else if (!fte) {
2961                 netdev_warn(dev, "found several Fast Transition element");
2962                 goto abort;
2963             } else {
2964                 memcpy(pos, fte, sizeof(*fte) + fte->datalen);
2965                 pos += sizeof(*fte) + fte->datalen;
2966                 fte = NULL;
2967             }
2968         }
2969         else {
2970             if (fte && !mde) {
2971                 memcpy(pos, fte, sizeof(*fte) + fte->datalen);
2972                 pos += sizeof(*fte) + fte->datalen;
2973                 fte = NULL;
2974             }
2975             memcpy(pos, elem, sizeof(*elem) + elem->datalen);
2976             pos += sizeof(*elem) + elem->datalen;
2977         }
2978     }
2979     if (fte) {
2980         memcpy(pos, fte, sizeof(*fte) + fte->datalen);
2981         pos += sizeof(*fte) + fte->datalen;
2982         fte = NULL;
2983     }
2984     kfree(vif->sta.ft_assoc_ies);
2985     vif->sta.ft_assoc_ies = ft_assoc_ies;
2986     vif->sta.ft_assoc_ies_len = pos - ft_assoc_ies;
2987     if (vif->sta.flags & ECRNX_STA_FT_OVER_DS) {
2988         struct sm_connect_cfm sm_connect_cfm;
2989         struct cfg80211_connect_params sme;
2990         memset(&sme, 0, sizeof(sme));
2991         rsne = cfg80211_find_ecrnx_elem(WLAN_EID_RSN, vif->sta.ft_assoc_ies,
2992                                   vif->sta.ft_assoc_ies_len);
2993         if (rsne && ecrnx_rsne_to_connect_params(rsne, &sme)) {
2994             netdev_warn(dev, "FT RSN parsing failed\n");
2995             return 0;
2996         }
2997         sme.ssid_len = vif->sta.ft_assoc_ies[1];
2998         sme.ssid = &vif->sta.ft_assoc_ies[2];
2999         sme.bssid = vif->sta.ft_target_ap;
3000         sme.ie = &vif->sta.ft_assoc_ies[2 + sme.ssid_len];
3001         sme.ie_len = vif->sta.ft_assoc_ies_len - (2 + sme.ssid_len);
3002         sme.auth_type = NL80211_AUTHTYPE_FT;
3003         ecrnx_send_sm_connect_req(ecrnx_hw, vif, &sme, &sm_connect_cfm);
3004         vif->sta.flags &= ~ECRNX_STA_FT_OVER_DS;
3005     } else if (vif->sta.flags & ECRNX_STA_FT_OVER_AIR) {
3006         uint8_t ssid_len;
3007         vif->sta.flags &= ~ECRNX_STA_FT_OVER_AIR;
3008         ssid_len = vif->sta.ft_assoc_ies[1] + 2;
3009         if (ecrnx_send_sm_ft_auth_rsp(ecrnx_hw, vif, &vif->sta.ft_assoc_ies[ssid_len],
3010                                      vif->sta.ft_assoc_ies_len - ssid_len))
3011             netdev_err(dev, "FT Over Air: Failed to send updated assoc elem\n");
3012     }
3013     return 0;
3014 abort:
3015     kfree(ft_assoc_ies);
3016     return 0;
3017 }
3018
3019 /**
3020  * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold.
3021  */
3022 static int ecrnx_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
3023                                   struct net_device *dev,
3024                                   int32_t rssi_thold, uint32_t rssi_hyst)
3025 {
3026     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3027     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3028
3029     return ecrnx_send_cfg_rssi_req(ecrnx_hw, ecrnx_vif->vif_index, rssi_thold, rssi_hyst);
3030 }
3031
3032 /**
3033  *
3034  * @channel_switch: initiate channel-switch procedure (with CSA). Driver is
3035  *      responsible for veryfing if the switch is possible. Since this is
3036  *      inherently tricky driver may decide to disconnect an interface later
3037  *      with cfg80211_stop_iface(). This doesn't mean driver can accept
3038  *      everything. It should do it's best to verify requests and reject them
3039  *      as soon as possible.
3040  */
3041 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
3042 static int ecrnx_cfg80211_channel_switch(struct wiphy *wiphy,
3043                                  struct net_device *dev,
3044                                  struct cfg80211_csa_settings *params)
3045 {
3046     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3047     struct ecrnx_vif *vif = netdev_priv(dev);
3048     struct ecrnx_ipc_elem_var elem;
3049     struct ecrnx_bcn *bcn, *bcn_after;
3050     struct ecrnx_csa *csa;
3051     u16 csa_oft[BCN_MAX_CSA_CPT];
3052     u8 *buf;
3053     int i, error = 0;
3054
3055
3056     if (vif->ap.csa)
3057         return -EBUSY;
3058
3059     if (params->n_counter_offsets_beacon > BCN_MAX_CSA_CPT)
3060         return -EINVAL;
3061
3062     /* Build the new beacon with CSA IE */
3063     bcn = &vif->ap.bcn;
3064     buf = ecrnx_build_bcn(bcn, &params->beacon_csa);
3065     if (!buf)
3066         return -ENOMEM;
3067
3068     memset(csa_oft, 0, sizeof(csa_oft));
3069     for (i = 0; i < params->n_counter_offsets_beacon; i++)
3070     {
3071         csa_oft[i] = params->counter_offsets_beacon[i] + bcn->head_len +
3072             bcn->tim_len;
3073     }
3074
3075     /* If count is set to 0 (i.e anytime after this beacon) force it to 2 */
3076     if (params->count == 0) {
3077         params->count = 2;
3078         for (i = 0; i < params->n_counter_offsets_beacon; i++)
3079         {
3080             buf[csa_oft[i]] = 2;
3081         }
3082     }
3083
3084     if ((error = ecrnx_ipc_elem_var_allocs(ecrnx_hw, &elem, bcn->len,
3085                                           DMA_TO_DEVICE, buf, NULL, NULL))) {
3086         goto end;
3087     }
3088
3089     /* Build the beacon to use after CSA. It will only be sent to fw once
3090        CSA is over, but do it before sending the beacon as it must be ready
3091        when CSA is finished. */
3092     csa = kzalloc(sizeof(struct ecrnx_csa), GFP_KERNEL);
3093     if (!csa) {
3094         error = -ENOMEM;
3095         goto end;
3096     }
3097
3098     bcn_after = &csa->bcn;
3099     buf = ecrnx_build_bcn(bcn_after, &params->beacon_after);
3100     if (!buf) {
3101         error = -ENOMEM;
3102         ecrnx_del_csa(vif);
3103         goto end;
3104     }
3105
3106     if ((error = ecrnx_ipc_elem_var_allocs(ecrnx_hw, &csa->elem, bcn_after->len,
3107                                           DMA_TO_DEVICE, buf, NULL, NULL))) {
3108         goto end;
3109     }
3110
3111     vif->ap.csa = csa;
3112     csa->vif = vif;
3113     csa->chandef = params->chandef;
3114
3115     /* Send new Beacon. FW will extract channel and count from the beacon */
3116     error = ecrnx_send_bcn_change(ecrnx_hw, vif->vif_index, elem.dma_addr,
3117                                  bcn->len, bcn->head_len, bcn->tim_len, csa_oft);
3118
3119     if (error) {
3120         ecrnx_del_csa(vif);
3121         goto end;
3122     } else {
3123         INIT_WORK(&csa->work, ecrnx_csa_finish);
3124         cfg80211_ch_switch_started_notify(dev, &csa->chandef, params->count);
3125     }
3126
3127   end:
3128     ecrnx_ipc_elem_var_deallocs(ecrnx_hw, &elem);
3129     return error;
3130 }
3131 #endif
3132
3133 /*
3134  * @tdls_mgmt: prepare TDLS action frame packets and forward them to FW
3135  */
3136 static int ecrnx_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
3137                         const u8 *peer, u8 action_code,  u8 dialog_token,
3138                         u16 status_code, u32 peer_capability,
3139                         bool initiator, const u8 *buf, size_t len)
3140 {
3141     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3142     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3143     int ret = 0;
3144
3145     /* make sure we support TDLS */
3146     if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
3147         return -ENOTSUPP;
3148
3149     /* make sure we are in station mode (and connected) */
3150     if ((ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_STATION) ||
3151         (!ecrnx_vif->up) || (!ecrnx_vif->sta.ap))
3152         return -ENOTSUPP;
3153
3154     /* only one TDLS link is supported */
3155     if ((action_code == WLAN_TDLS_SETUP_REQUEST) &&
3156         (ecrnx_vif->sta.tdls_sta) &&
3157         (ecrnx_vif->tdls_status == TDLS_LINK_ACTIVE)) {
3158         ECRNX_ERR("%s: only one TDLS link is supported!\n", __func__);
3159         return -ENOTSUPP;
3160     }
3161
3162     if ((action_code == WLAN_TDLS_DISCOVERY_REQUEST) &&
3163         (ecrnx_hw->mod_params->ps_on)) {
3164         ECRNX_ERR("%s: discovery request is not supported when "
3165                 "power-save is enabled!\n", __func__);
3166         return -ENOTSUPP;
3167     }
3168
3169     switch (action_code) {
3170     case WLAN_TDLS_SETUP_RESPONSE:
3171         /* only one TDLS link is supported */
3172         if ((status_code == 0) &&
3173             (ecrnx_vif->sta.tdls_sta) &&
3174             (ecrnx_vif->tdls_status == TDLS_LINK_ACTIVE)) {
3175             ECRNX_ERR("%s: only one TDLS link is supported!\n", __func__);
3176             status_code = WLAN_STATUS_REQUEST_DECLINED;
3177         }
3178         /* fall-through */
3179     case WLAN_TDLS_SETUP_REQUEST:
3180     case WLAN_TDLS_TEARDOWN:
3181     case WLAN_TDLS_DISCOVERY_REQUEST:
3182     case WLAN_TDLS_SETUP_CONFIRM:
3183     case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
3184         ret = ecrnx_tdls_send_mgmt_packet_data(ecrnx_hw, ecrnx_vif, peer, action_code,
3185                 dialog_token, status_code, peer_capability, initiator, buf, len, 0, NULL);
3186         break;
3187
3188     default:
3189         ECRNX_ERR("%s: Unknown TDLS mgmt/action frame %pM\n",
3190                 __func__, peer);
3191         ret = -EOPNOTSUPP;
3192         break;
3193     }
3194
3195     if (action_code == WLAN_TDLS_SETUP_REQUEST) {
3196         ecrnx_vif->tdls_status = TDLS_SETUP_REQ_TX;
3197     } else if (action_code == WLAN_TDLS_SETUP_RESPONSE) {
3198         ecrnx_vif->tdls_status = TDLS_SETUP_RSP_TX;
3199     } else if ((action_code == WLAN_TDLS_SETUP_CONFIRM) && (ret == CO_OK)) {
3200         ecrnx_vif->tdls_status = TDLS_LINK_ACTIVE;
3201         /* Set TDLS active */
3202         ecrnx_vif->sta.tdls_sta->tdls.active = true;
3203     }
3204
3205     return ret;
3206 }
3207
3208 /*
3209  * @tdls_oper: execute TDLS operation
3210  */
3211 static int ecrnx_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
3212         const u8 *peer, enum nl80211_tdls_operation oper)
3213 {
3214     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3215     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3216     int error;
3217
3218     if (oper != NL80211_TDLS_DISABLE_LINK)
3219         return 0;
3220
3221     if (!ecrnx_vif->sta.tdls_sta) {
3222         ECRNX_ERR("%s: TDLS station %pM does not exist\n", __func__, peer);
3223         return -ENOLINK;
3224     }
3225
3226     if (memcmp(ecrnx_vif->sta.tdls_sta->mac_addr, peer, ETH_ALEN) == 0) {
3227         /* Disable Channel Switch */
3228         if (!ecrnx_send_tdls_cancel_chan_switch_req(ecrnx_hw, ecrnx_vif,
3229                                                    ecrnx_vif->sta.tdls_sta,
3230                                                    NULL))
3231             ecrnx_vif->sta.tdls_sta->tdls.chsw_en = false;
3232
3233         netdev_info(dev, "Del TDLS sta %d (%pM)",
3234                 ecrnx_vif->sta.tdls_sta->sta_idx,
3235                 ecrnx_vif->sta.tdls_sta->mac_addr);
3236         /* Ensure that we won't process PS change ind */
3237         spin_lock_bh(&ecrnx_hw->cb_lock);
3238         ecrnx_vif->sta.tdls_sta->ps.active = false;
3239         ecrnx_vif->sta.tdls_sta->valid = false;
3240         spin_unlock_bh(&ecrnx_hw->cb_lock);
3241         ecrnx_txq_sta_deinit(ecrnx_hw, ecrnx_vif->sta.tdls_sta);
3242         error = ecrnx_send_me_sta_del(ecrnx_hw, ecrnx_vif->sta.tdls_sta->sta_idx, true);
3243         if ((error != 0) && (error != -EPIPE))
3244             return error;
3245
3246 #ifdef CONFIG_ECRNX_BFMER
3247             // Disable Beamformer if supported
3248             ecrnx_bfmer_report_del(ecrnx_hw, ecrnx_vif->sta.tdls_sta);
3249             ecrnx_mu_group_sta_del(ecrnx_hw, ecrnx_vif->sta.tdls_sta);
3250 #endif /* CONFIG_ECRNX_BFMER */
3251
3252         /* Set TDLS not active */
3253         ecrnx_vif->sta.tdls_sta->tdls.active = false;
3254         ecrnx_dbgfs_unregister_sta(ecrnx_hw, ecrnx_vif->sta.tdls_sta);
3255         // Remove TDLS station
3256         ecrnx_vif->tdls_status = TDLS_LINK_IDLE;
3257         ecrnx_vif->sta.tdls_sta = NULL;
3258     }
3259
3260     return 0;
3261 }
3262
3263 /*
3264  * @tdls_channel_switch: enable TDLS channel switch
3265  */
3266 static int ecrnx_cfg80211_tdls_channel_switch(struct wiphy *wiphy,
3267                                       struct net_device *dev,
3268                                       const u8 *addr, u8 oper_class,
3269                                       struct cfg80211_chan_def *chandef)
3270 {
3271     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3272     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3273     struct ecrnx_sta *ecrnx_sta = ecrnx_vif->sta.tdls_sta;
3274     struct tdls_chan_switch_cfm cfm;
3275     int error;
3276
3277     if ((!ecrnx_sta) || (memcmp(addr, ecrnx_sta->mac_addr, ETH_ALEN))) {
3278         ECRNX_ERR("%s: TDLS station %pM doesn't exist\n", __func__, addr);
3279         return -ENOLINK;
3280     }
3281
3282     if (!ecrnx_sta->tdls.chsw_allowed) {
3283         ECRNX_ERR("%s: TDLS station %pM does not support TDLS channel switch\n", __func__, addr);
3284         return -ENOTSUPP;
3285     }
3286
3287     error = ecrnx_send_tdls_chan_switch_req(ecrnx_hw, ecrnx_vif, ecrnx_sta,
3288                                            ecrnx_sta->tdls.initiator,
3289                                            oper_class, chandef, &cfm);
3290     if (error)
3291         return error;
3292
3293     if (!cfm.status) {
3294         ecrnx_sta->tdls.chsw_en = true;
3295         return 0;
3296     } else {
3297         ECRNX_ERR("%s: TDLS channel switch already enabled and only one is supported\n", __func__);
3298         return -EALREADY;
3299     }
3300 }
3301
3302 /*
3303  * @tdls_cancel_channel_switch: disable TDLS channel switch
3304  */
3305 static void ecrnx_cfg80211_tdls_cancel_channel_switch(struct wiphy *wiphy,
3306                                               struct net_device *dev,
3307                                               const u8 *addr)
3308 {
3309     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3310     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3311     struct ecrnx_sta *ecrnx_sta = ecrnx_vif->sta.tdls_sta;
3312     struct tdls_cancel_chan_switch_cfm cfm;
3313
3314     if (!ecrnx_sta)
3315         return;
3316
3317     if (!ecrnx_send_tdls_cancel_chan_switch_req(ecrnx_hw, ecrnx_vif,
3318                                                ecrnx_sta, &cfm))
3319         ecrnx_sta->tdls.chsw_en = false;
3320 }
3321
3322 /**
3323  * @change_bss: Modify parameters for a given BSS (mainly for AP mode).
3324  */
3325 static int ecrnx_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev,
3326                              struct bss_parameters *params)
3327 {
3328     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3329     int res =  -EOPNOTSUPP;
3330
3331     if (((ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_AP) ||
3332          (ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_P2P_GO)) &&
3333         (params->ap_isolate > -1)) {
3334
3335         if (params->ap_isolate)
3336             ecrnx_vif->ap.flags |= ECRNX_AP_ISOLATE;
3337         else
3338             ecrnx_vif->ap.flags &= ~ECRNX_AP_ISOLATE;
3339
3340         res = 0;
3341     }
3342
3343     return res;
3344 }
3345
3346
3347 /**
3348  * @get_station: get station information for the station identified by @mac
3349  */
3350 static int ecrnx_fill_station_info(struct ecrnx_sta *sta, struct ecrnx_vif *vif,
3351                                   struct station_info *sinfo)
3352 {
3353     struct ecrnx_sta_stats *stats = &sta->stats;
3354     struct rx_vector_1 *rx_vect1 = &stats->last_rx.rx_vect1;
3355
3356     // Generic info
3357     sinfo->generation = vif->generation;
3358
3359     //sinfo->inactive_time = jiffies_to_msecs(jiffies - stats->last_act);
3360     sinfo->rx_bytes = stats->rx_bytes;
3361     sinfo->tx_bytes = stats->tx_bytes;
3362     sinfo->tx_packets = stats->tx_pkts;
3363     sinfo->rx_packets = stats->rx_pkts;
3364     sinfo->signal = rx_vect1->rssi1;
3365     sinfo->tx_failed = 1;
3366
3367 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
3368     switch (rx_vect1->ch_bw) {
3369         case PHY_CHNL_BW_20:
3370             sinfo->rxrate.bw = RATE_INFO_BW_20;
3371             break;
3372         case PHY_CHNL_BW_40:
3373             sinfo->rxrate.bw = RATE_INFO_BW_40;
3374             break;
3375         case PHY_CHNL_BW_80:
3376             sinfo->rxrate.bw = RATE_INFO_BW_80;
3377             break;
3378         case PHY_CHNL_BW_160:
3379             sinfo->rxrate.bw = RATE_INFO_BW_160;
3380             break;
3381         default:
3382 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
3383             sinfo->rxrate.bw = RATE_INFO_BW_HE_RU;
3384 #else
3385             sinfo->rxrate.bw = RATE_INFO_BW_160;
3386 #endif
3387             break;
3388     }
3389 #endif
3390
3391     switch (rx_vect1->format_mod) {
3392         case FORMATMOD_NON_HT:
3393         case FORMATMOD_NON_HT_DUP_OFDM:
3394             sinfo->rxrate.flags = 0;
3395             sinfo->rxrate.legacy = legrates_lut[rx_vect1->leg_rate].rate;
3396             break;
3397         case FORMATMOD_HT_MF:
3398         case FORMATMOD_HT_GF:
3399             sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS;
3400             if (rx_vect1->ht.short_gi)
3401                 sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
3402             sinfo->rxrate.mcs = rx_vect1->ht.mcs;
3403             break;
3404         case FORMATMOD_VHT:
3405             sinfo->rxrate.flags = RATE_INFO_FLAGS_VHT_MCS;
3406             if (rx_vect1->vht.short_gi)
3407                 sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
3408             sinfo->rxrate.mcs = rx_vect1->vht.mcs;
3409             sinfo->rxrate.nss = rx_vect1->vht.nss;
3410             break;
3411 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
3412 #if CONFIG_ECRNX_HE
3413         case FORMATMOD_HE_MU:
3414             sinfo->rxrate.he_ru_alloc = rx_vect1->he.ru_size;
3415             break;
3416         case FORMATMOD_HE_SU:
3417         case FORMATMOD_HE_ER:
3418         case FORMATMOD_HE_TB:
3419             sinfo->rxrate.flags = RATE_INFO_FLAGS_HE_MCS;
3420             sinfo->rxrate.mcs = rx_vect1->he.mcs;
3421             sinfo->rxrate.nss = rx_vect1->he.nss;
3422             sinfo->rxrate.he_gi = rx_vect1->he.gi_type;
3423             sinfo->rxrate.he_dcm = rx_vect1->he.dcm;
3424             break;
3425 #endif
3426 #endif
3427         default :
3428             return -EINVAL;
3429     }
3430
3431 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
3432     sinfo->filled |= (STATION_INFO_INACTIVE_TIME |
3433 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
3434                      STATION_INFO_RX_BYTES64 |
3435                      STATION_INFO_TX_BYTES64 |
3436 #endif
3437                      STATION_INFO_RX_PACKETS |
3438                      STATION_INFO_TX_PACKETS |
3439                      STATION_INFO_SIGNAL |
3440                      STATION_INFO_RX_BITRATE);
3441 #else
3442     sinfo->filled = (BIT(NL80211_STA_INFO_RX_BYTES64)    |
3443                      BIT(NL80211_STA_INFO_TX_BYTES64)    |
3444                      BIT(NL80211_STA_INFO_RX_PACKETS)    |
3445                      BIT(NL80211_STA_INFO_TX_PACKETS)    |
3446                      BIT(NL80211_STA_INFO_SIGNAL)        |
3447                      BIT(NL80211_STA_INFO_TX_BITRATE)    |
3448                      BIT(NL80211_STA_INFO_TX_FAILED)     |
3449                      BIT(NL80211_STA_INFO_RX_BITRATE));
3450 #endif
3451
3452     // Mesh specific info
3453     if (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_MESH_POINT)
3454     {
3455         struct mesh_peer_info_cfm peer_info_cfm;
3456         if (ecrnx_send_mesh_peer_info_req(vif->ecrnx_hw, vif, sta->sta_idx,
3457                                          &peer_info_cfm))
3458             return -ENOMEM;
3459
3460         peer_info_cfm.last_bcn_age = peer_info_cfm.last_bcn_age / 1000;
3461         if (peer_info_cfm.last_bcn_age < sinfo->inactive_time)
3462             sinfo->inactive_time = peer_info_cfm.last_bcn_age;
3463
3464         sinfo->llid = peer_info_cfm.local_link_id;
3465         sinfo->plid = peer_info_cfm.peer_link_id;
3466         sinfo->plink_state = peer_info_cfm.link_state;
3467 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
3468         sinfo->local_pm = peer_info_cfm.local_ps_mode;
3469         sinfo->peer_pm = peer_info_cfm.peer_ps_mode;
3470         sinfo->nonpeer_pm = peer_info_cfm.non_peer_ps_mode;
3471 #endif
3472         sinfo->filled |= (BIT(NL80211_STA_INFO_LLID) |
3473                           BIT(NL80211_STA_INFO_PLID) |
3474                           BIT(NL80211_STA_INFO_PLINK_STATE) |
3475 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
3476                           BIT(NL80211_STA_INFO_LOCAL_PM) |
3477                           BIT(NL80211_STA_INFO_PEER_PM) |
3478                           BIT(NL80211_STA_INFO_NONPEER_PM)|
3479 #endif
3480                           0);
3481     }
3482
3483     sinfo->txrate.legacy = 0x6818;
3484
3485     return 0;
3486 }
3487
3488 static int ecrnx_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
3489 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))
3490                     u8 *mac,
3491 #else
3492                     const u8 *mac,
3493 #endif
3494                      struct station_info *sinfo)
3495 {
3496     struct ecrnx_vif *vif = netdev_priv(dev);
3497     struct ecrnx_sta *sta = NULL;
3498
3499     if (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_MONITOR)
3500         return -EINVAL;
3501     else if ((ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_STATION) ||
3502              (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_CLIENT)) {
3503         if (vif->sta.ap && ether_addr_equal(vif->sta.ap->mac_addr, mac))
3504             sta = vif->sta.ap;
3505     }
3506     else
3507     {
3508         struct ecrnx_sta *sta_iter;
3509         list_for_each_entry(sta_iter, &vif->ap.sta_list, list) {
3510             if (sta_iter->valid && ether_addr_equal(sta_iter->mac_addr, mac)) {
3511                 sta = sta_iter;
3512                 break;
3513             }
3514         }
3515     }
3516
3517     if (sta)
3518         return ecrnx_fill_station_info(sta, vif, sinfo);
3519
3520     return -EINVAL;
3521 }
3522
3523 int ecrnx_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
3524                                       int idx, u8 *mac, struct station_info *sinfo)
3525 {
3526     struct ecrnx_vif *vif = netdev_priv(dev);
3527     struct ecrnx_sta *sta = NULL;
3528
3529     if (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_MONITOR)
3530         return -EINVAL;
3531     else if ((ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_STATION) ||
3532              (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_CLIENT)) {
3533         if ((idx == 0) && vif->sta.ap && vif->sta.ap->valid)
3534             sta = vif->sta.ap;
3535     } else {
3536         struct ecrnx_sta *sta_iter;
3537         int i = 0;
3538         list_for_each_entry(sta_iter, &vif->ap.sta_list, list) {
3539             if (i == idx) {
3540                 sta = sta_iter;
3541                 break;
3542             }
3543             i++;
3544         }
3545     }
3546
3547     if (sta == NULL)
3548         return -ENOENT;
3549
3550
3551     memcpy(mac, &sta->mac_addr, ETH_ALEN);
3552
3553     return ecrnx_fill_station_info(sta, vif, sinfo);
3554 }
3555
3556 /**
3557  * @add_mpath: add a fixed mesh path
3558  */
3559 static int ecrnx_cfg80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
3560                                    const u8 *dst, const u8 *next_hop)
3561 {
3562     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3563     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3564     struct mesh_path_update_cfm cfm;
3565
3566     if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3567         return -ENOTSUPP;
3568
3569     return ecrnx_send_mesh_path_update_req(ecrnx_hw, ecrnx_vif, dst, next_hop, &cfm);
3570 }
3571
3572 /**
3573  * @del_mpath: delete a given mesh path
3574  */
3575 static int ecrnx_cfg80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
3576                                    const u8 *dst)
3577 {
3578     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3579     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3580     struct mesh_path_update_cfm cfm;
3581
3582     if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3583         return -ENOTSUPP;
3584
3585     return ecrnx_send_mesh_path_update_req(ecrnx_hw, ecrnx_vif, dst, NULL, &cfm);
3586 }
3587
3588 /**
3589  * @change_mpath: change a given mesh path
3590  */
3591 static int ecrnx_cfg80211_change_mpath(struct wiphy *wiphy, struct net_device *dev,
3592                                       const u8 *dst, const u8 *next_hop)
3593 {
3594     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3595     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3596     struct mesh_path_update_cfm cfm;
3597
3598     if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3599         return -ENOTSUPP;
3600
3601     return ecrnx_send_mesh_path_update_req(ecrnx_hw, ecrnx_vif, dst, next_hop, &cfm);
3602 }
3603
3604 /**
3605  * @get_mpath: get a mesh path for the given parameters
3606  */
3607 static int ecrnx_cfg80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
3608                                    u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
3609 {
3610     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3611     struct ecrnx_mesh_path *mesh_path = NULL;
3612     struct ecrnx_mesh_path *cur;
3613
3614     if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3615         return -ENOTSUPP;
3616
3617     list_for_each_entry(cur, &ecrnx_vif->ap.mpath_list, list) {
3618         /* Compare the path target address and the provided destination address */
3619         if (memcmp(dst, &cur->tgt_mac_addr, ETH_ALEN)) {
3620             continue;
3621         }
3622
3623         mesh_path = cur;
3624         break;
3625     }
3626
3627     if (mesh_path == NULL)
3628         return -ENOENT;
3629
3630     /* Copy next HOP MAC address */
3631     if (mesh_path->nhop_sta)
3632         memcpy(next_hop, &mesh_path->nhop_sta->mac_addr, ETH_ALEN);
3633
3634     /* Fill path information */
3635     pinfo->filled = 0;
3636     pinfo->generation = ecrnx_vif->generation;
3637
3638     return 0;
3639 }
3640
3641 /**
3642  * @dump_mpath: dump mesh path callback -- resume dump at index @idx
3643  */
3644 static int ecrnx_cfg80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
3645                                     int idx, u8 *dst, u8 *next_hop,
3646                                     struct mpath_info *pinfo)
3647 {
3648     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3649     struct ecrnx_mesh_path *mesh_path = NULL;
3650     struct ecrnx_mesh_path *cur;
3651     int i = 0;
3652
3653     if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3654         return -ENOTSUPP;
3655
3656     list_for_each_entry(cur, &ecrnx_vif->ap.mpath_list, list) {
3657         if (i < idx) {
3658             i++;
3659             continue;
3660         }
3661
3662         mesh_path = cur;
3663         break;
3664     }
3665
3666     if (mesh_path == NULL)
3667         return -ENOENT;
3668
3669     /* Copy target and next hop MAC address */
3670     memcpy(dst, &mesh_path->tgt_mac_addr, ETH_ALEN);
3671     if (mesh_path->nhop_sta)
3672         memcpy(next_hop, &mesh_path->nhop_sta->mac_addr, ETH_ALEN);
3673
3674     /* Fill path information */
3675     pinfo->filled = 0;
3676     pinfo->generation = ecrnx_vif->generation;
3677
3678     return 0;
3679 }
3680
3681 /**
3682  * @get_mpp: get a mesh proxy path for the given parameters
3683  */
3684 static int ecrnx_cfg80211_get_mpp(struct wiphy *wiphy, struct net_device *dev,
3685                                  u8 *dst, u8 *mpp, struct mpath_info *pinfo)
3686 {
3687     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3688     struct ecrnx_mesh_proxy *mesh_proxy = NULL;
3689     struct ecrnx_mesh_proxy *cur;
3690
3691     if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3692         return -ENOTSUPP;
3693
3694     list_for_each_entry(cur, &ecrnx_vif->ap.proxy_list, list) {
3695         if (cur->local) {
3696             continue;
3697         }
3698
3699         /* Compare the path target address and the provided destination address */
3700         if (memcmp(dst, &cur->ext_sta_addr, ETH_ALEN)) {
3701             continue;
3702         }
3703
3704         mesh_proxy = cur;
3705         break;
3706     }
3707
3708     if (mesh_proxy == NULL)
3709         return -ENOENT;
3710
3711     memcpy(mpp, &mesh_proxy->proxy_addr, ETH_ALEN);
3712
3713     /* Fill path information */
3714     pinfo->filled = 0;
3715     pinfo->generation = ecrnx_vif->generation;
3716
3717     return 0;
3718 }
3719
3720 /**
3721  * @dump_mpp: dump mesh proxy path callback -- resume dump at index @idx
3722  */
3723 static int ecrnx_cfg80211_dump_mpp(struct wiphy *wiphy, struct net_device *dev,
3724                                   int idx, u8 *dst, u8 *mpp, struct mpath_info *pinfo)
3725 {
3726     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3727     struct ecrnx_mesh_proxy *mesh_proxy = NULL;
3728     struct ecrnx_mesh_proxy *cur;
3729     int i = 0;
3730
3731     if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3732         return -ENOTSUPP;
3733
3734     list_for_each_entry(cur, &ecrnx_vif->ap.proxy_list, list) {
3735         if (cur->local) {
3736             continue;
3737         }
3738
3739         if (i < idx) {
3740             i++;
3741             continue;
3742         }
3743
3744         mesh_proxy = cur;
3745         break;
3746     }
3747
3748     if (mesh_proxy == NULL)
3749         return -ENOENT;
3750
3751     /* Copy target MAC address */
3752     memcpy(dst, &mesh_proxy->ext_sta_addr, ETH_ALEN);
3753     memcpy(mpp, &mesh_proxy->proxy_addr, ETH_ALEN);
3754
3755     /* Fill path information */
3756     pinfo->filled = 0;
3757     pinfo->generation = ecrnx_vif->generation;
3758
3759     return 0;
3760 }
3761
3762 /**
3763  * @get_mesh_config: Get the current mesh configuration
3764  */
3765 static int ecrnx_cfg80211_get_mesh_config(struct wiphy *wiphy, struct net_device *dev,
3766                                          struct mesh_config *conf)
3767 {
3768     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3769
3770     if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3771         return -ENOTSUPP;
3772
3773     return 0;
3774 }
3775
3776 /**
3777  * @update_mesh_config: Update mesh parameters on a running mesh.
3778  */
3779 static int ecrnx_cfg80211_update_mesh_config(struct wiphy *wiphy, struct net_device *dev,
3780                                             u32 mask, const struct mesh_config *nconf)
3781 {
3782     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3783     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3784     struct mesh_update_cfm cfm;
3785     int status;
3786
3787     if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3788         return -ENOTSUPP;
3789
3790 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
3791     if (mask & CO_BIT(NL80211_MESHCONF_POWER_MODE - 1)) {
3792         ecrnx_vif->ap.next_mesh_pm = nconf->power_mode;
3793
3794         if (!list_empty(&ecrnx_vif->ap.sta_list)) {
3795             // If there are mesh links we don't want to update the power mode
3796             // It will be updated with ecrnx_update_mesh_power_mode() when the
3797             // ps mode of a link is updated or when a new link is added/removed
3798             mask &= ~BIT(NL80211_MESHCONF_POWER_MODE - 1);
3799
3800             if (!mask)
3801                 return 0;
3802         }
3803     }
3804 #endif
3805
3806     status = ecrnx_send_mesh_update_req(ecrnx_hw, ecrnx_vif, mask, nconf, &cfm);
3807
3808     if (!status && (cfm.status != 0))
3809         status = -EINVAL;
3810
3811     return status;
3812 }
3813
3814 /**
3815  * @join_mesh: join the mesh network with the specified parameters
3816  * (invoked with the wireless_dev mutex held)
3817  */
3818 static int ecrnx_cfg80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
3819                                    const struct mesh_config *conf, const struct mesh_setup *setup)
3820 {
3821     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3822     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3823     struct mesh_start_cfm mesh_start_cfm;
3824     int error = 0;
3825     u8 txq_status = 0;
3826     /* STA for BC/MC traffic */
3827     struct ecrnx_sta *sta;
3828
3829     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
3830
3831     if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3832         return -ENOTSUPP;
3833
3834     /* Forward the information to the UMAC */
3835     if ((error = ecrnx_send_mesh_start_req(ecrnx_hw, ecrnx_vif, conf, setup, &mesh_start_cfm))) {
3836         return error;
3837     }
3838
3839     /* Check the status */
3840     switch (mesh_start_cfm.status) {
3841         case CO_OK:
3842 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
3843             ecrnx_vif->ap.bcmc_index = mesh_start_cfm.bcmc_idx;
3844             ecrnx_vif->ap.bcn_interval = setup->beacon_interval;
3845 #endif
3846             ecrnx_vif->ap.flags = 0;
3847             ecrnx_vif->use_4addr = true;
3848 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
3849             if (setup->user_mpm)
3850                 ecrnx_vif->ap.flags |= ECRNX_AP_USER_MESH_PM;
3851 #endif
3852
3853             sta = &ecrnx_hw->sta_table[mesh_start_cfm.bcmc_idx];
3854             sta->valid = true;
3855             sta->aid = 0;
3856             sta->sta_idx = mesh_start_cfm.bcmc_idx;
3857             sta->ch_idx = mesh_start_cfm.ch_idx;
3858             sta->vif_idx = ecrnx_vif->vif_index;
3859             sta->qos = true;
3860             sta->acm = 0;
3861             sta->ps.active = false;
3862             sta->listen_interval = 5;
3863             ecrnx_mu_group_sta_init(sta, NULL);
3864             spin_lock_bh(&ecrnx_hw->cb_lock);
3865             ecrnx_chanctx_link(ecrnx_vif, mesh_start_cfm.ch_idx,
3866                               (struct cfg80211_chan_def *)(&setup->chandef));
3867             if (ecrnx_hw->cur_chanctx != mesh_start_cfm.ch_idx) {
3868                 txq_status = ECRNX_TXQ_STOP_CHAN;
3869             }
3870             ecrnx_txq_vif_init(ecrnx_hw, ecrnx_vif, txq_status);
3871             spin_unlock_bh(&ecrnx_hw->cb_lock);
3872
3873             netif_tx_start_all_queues(dev);
3874             netif_carrier_on(dev);
3875
3876             /* If the AP channel is already the active, we probably skip radar
3877                activation on MM_CHANNEL_SWITCH_IND (unless another vif use this
3878                ctxt). In anycase retest if radar detection must be activated
3879              */
3880             if (ecrnx_hw->cur_chanctx == mesh_start_cfm.ch_idx) {
3881                 ecrnx_radar_detection_enable_on_cur_channel(ecrnx_hw);
3882             }
3883             break;
3884
3885         case CO_BUSY:
3886             error = -EINPROGRESS;
3887             break;
3888
3889         default:
3890             error = -EIO;
3891             break;
3892     }
3893
3894     /* Print information about the operation */
3895     if (error) {
3896         netdev_info(dev, "Failed to start MP (%d)", error);
3897     } else {
3898         netdev_info(dev, "MP started: ch=%d, bcmc_idx=%d",
3899                     ecrnx_vif->ch_index, ecrnx_vif->ap.bcmc_index);
3900     }
3901
3902     return error;
3903 }
3904
3905 /**
3906  * @leave_mesh: leave the current mesh network
3907  * (invoked with the wireless_dev mutex held)
3908  */
3909 static int ecrnx_cfg80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
3910 {
3911     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3912     struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3913     struct mesh_stop_cfm mesh_stop_cfm;
3914     int error = 0;
3915
3916     error = ecrnx_send_mesh_stop_req(ecrnx_hw, ecrnx_vif, &mesh_stop_cfm);
3917
3918     if (error == 0) {
3919         /* Check the status */
3920         switch (mesh_stop_cfm.status) {
3921             case CO_OK:
3922                 spin_lock_bh(&ecrnx_hw->cb_lock);
3923                 ecrnx_chanctx_unlink(ecrnx_vif);
3924                 ecrnx_radar_cancel_cac(&ecrnx_hw->radar);
3925                 spin_unlock_bh(&ecrnx_hw->cb_lock);
3926                 /* delete BC/MC STA */
3927                 ecrnx_txq_vif_deinit(ecrnx_hw, ecrnx_vif);
3928                 ecrnx_del_bcn(&ecrnx_vif->ap.bcn);
3929
3930                 netif_tx_stop_all_queues(dev);
3931                 netif_carrier_off(dev);
3932
3933                 break;
3934
3935             default:
3936                 error = -EIO;
3937                 break;
3938         }
3939     }
3940
3941     if (error) {
3942         netdev_info(dev, "Failed to stop MP");
3943     } else {
3944         netdev_info(dev, "MP Stopped");
3945     }
3946
3947     return 0;
3948 }
3949
3950 #ifdef CONFIG_ECRNX_P2P
3951 #if LINUX_VERSION_CODE > KERNEL_VERSION(5, 8, 0)
3952 static void ecrnx_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy,
3953                                           struct wireless_dev *wdev,
3954                                           struct mgmt_frame_regs *upd)
3955 {
3956     struct ecrnx_vif *ecrnx_vif = netdev_priv(wdev->netdev);
3957
3958         ECRNX_DBG(ECRNX_FN_ENTRY_STR);
3959         
3960         if (ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_STATION)
3961         {               
3962                 ecrnx_vif->mgmt_reg_stypes = upd->interface_stypes & BIT(IEEE80211_STYPE_PROBE_REQ >> 4);
3963     }
3964 }
3965 #else
3966 static void ecrnx_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
3967                                    struct wireless_dev *wdev,
3968                                    u16 frame_type, bool reg)
3969 {
3970     struct ecrnx_vif *ecrnx_vif = netdev_priv(wdev->netdev);
3971
3972         u16 mgmt_type;
3973
3974         mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
3975
3976         if (reg)
3977                 ecrnx_vif->mgmt_reg_stypes |= BIT(mgmt_type);
3978         else
3979                 ecrnx_vif->mgmt_reg_stypes &= ~BIT(mgmt_type);
3980 }                          
3981 #endif
3982 #endif
3983
3984 static struct cfg80211_ops ecrnx_cfg80211_ops = {
3985     .add_virtual_intf = ecrnx_cfg80211_add_iface,
3986     .del_virtual_intf = ecrnx_cfg80211_del_iface,
3987     .change_virtual_intf = ecrnx_cfg80211_change_iface,
3988     .start_p2p_device = ecrnx_cfg80211_start_p2p_device,
3989     .stop_p2p_device = ecrnx_cfg80211_stop_p2p_device,
3990     .scan = ecrnx_cfg80211_scan,
3991 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
3992     .abort_scan = ecrnx_cfg80211_abort_scan,
3993 #endif
3994     .connect = ecrnx_cfg80211_connect,
3995     .disconnect = ecrnx_cfg80211_disconnect,
3996     .add_key = ecrnx_cfg80211_add_key,
3997     .get_key = ecrnx_cfg80211_get_key,
3998     .del_key = ecrnx_cfg80211_del_key,
3999     .set_default_key = ecrnx_cfg80211_set_default_key,
4000     .set_default_mgmt_key = ecrnx_cfg80211_set_default_mgmt_key,
4001     .add_station = ecrnx_cfg80211_add_station,
4002     .del_station = ecrnx_cfg80211_del_station,
4003     .change_station = ecrnx_cfg80211_change_station,
4004     .mgmt_tx = ecrnx_cfg80211_mgmt_tx,
4005     .start_ap = ecrnx_cfg80211_start_ap,
4006     .change_beacon = ecrnx_cfg80211_change_beacon,
4007     .stop_ap = ecrnx_cfg80211_stop_ap,
4008     .set_monitor_channel = ecrnx_cfg80211_set_monitor_channel,
4009     .probe_client = ecrnx_cfg80211_probe_client,
4010     .set_wiphy_params = ecrnx_cfg80211_set_wiphy_params,
4011     .set_txq_params = ecrnx_cfg80211_set_txq_params,
4012     .set_tx_power = ecrnx_cfg80211_set_tx_power,
4013 //    .get_tx_power = ecrnx_cfg80211_get_tx_power,
4014     .set_power_mgmt = ecrnx_cfg80211_set_power_mgmt,
4015     .get_station = ecrnx_cfg80211_get_station,
4016     .remain_on_channel = ecrnx_cfg80211_remain_on_channel,
4017     .cancel_remain_on_channel = ecrnx_cfg80211_cancel_remain_on_channel,
4018     .dump_survey = ecrnx_cfg80211_dump_survey,
4019     .get_channel = ecrnx_cfg80211_get_channel,
4020 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
4021     .start_radar_detection = ecrnx_cfg80211_start_radar_detection,
4022     .update_ft_ies = ecrnx_cfg80211_update_ft_ies,
4023 #endif
4024     .set_cqm_rssi_config = ecrnx_cfg80211_set_cqm_rssi_config,
4025 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
4026     .channel_switch = ecrnx_cfg80211_channel_switch,
4027 #endif
4028 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
4029     .tdls_channel_switch = ecrnx_cfg80211_tdls_channel_switch,
4030     .tdls_cancel_channel_switch = ecrnx_cfg80211_tdls_cancel_channel_switch,
4031 #endif
4032     .tdls_mgmt = ecrnx_cfg80211_tdls_mgmt,
4033     .tdls_oper = ecrnx_cfg80211_tdls_oper,
4034     .change_bss = ecrnx_cfg80211_change_bss,
4035 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
4036     .external_auth = ecrnx_cfg80211_external_auth,
4037 #endif
4038
4039 #ifdef CONFIG_ECRNX_P2P
4040 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
4041         .update_mgmt_frame_registrations =
4042                 ecrnx_cfg80211_update_mgmt_frame_registrations,
4043 #else
4044     .mgmt_frame_register = ecrnx_cfg80211_mgmt_frame_register,
4045 #endif
4046 #endif
4047
4048 };
4049
4050
4051 /*********************************************************************
4052  * Init/Exit functions
4053  *********************************************************************/
4054 static void ecrnx_wdev_unregister(struct ecrnx_hw *ecrnx_hw)
4055 {
4056     struct ecrnx_vif *ecrnx_vif, *tmp;
4057
4058     rtnl_lock();
4059     list_for_each_entry_safe(ecrnx_vif, tmp, &ecrnx_hw->vifs, list) {
4060         ecrnx_cfg80211_del_iface(ecrnx_hw->wiphy, &ecrnx_vif->wdev);
4061     }
4062     rtnl_unlock();
4063 }
4064
4065 static void ecrnx_set_vers(struct ecrnx_hw *ecrnx_hw)
4066 {
4067     u32 vers = ecrnx_hw->version_cfm.version_lmac;
4068
4069     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
4070
4071     snprintf(ecrnx_hw->wiphy->fw_version,
4072              sizeof(ecrnx_hw->wiphy->fw_version), "%d.%d.%d.%d",
4073              (vers & (0xff << 24)) >> 24, (vers & (0xff << 16)) >> 16,
4074              (vers & (0xff <<  8)) >>  8, (vers & (0xff <<  0)) >>  0);
4075     ecrnx_hw->machw_type = ecrnx_machw_type(ecrnx_hw->version_cfm.version_machw_2);
4076 }
4077
4078 static void ecrnx_reg_notifier(struct wiphy *wiphy,
4079                               struct regulatory_request *request)
4080 {
4081     struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
4082
4083     // For now trust all initiator
4084     ecrnx_radar_set_domain(&ecrnx_hw->radar, request->dfs_region);
4085     ecrnx_send_me_chan_config_req(ecrnx_hw);
4086 }
4087
4088 static void ecrnx_enable_mesh(struct ecrnx_hw *ecrnx_hw)
4089 {
4090     struct wiphy *wiphy = ecrnx_hw->wiphy;
4091
4092     if (!ecrnx_mod_params.mesh)
4093         return;
4094
4095     ecrnx_cfg80211_ops.add_mpath = ecrnx_cfg80211_add_mpath;
4096     ecrnx_cfg80211_ops.del_mpath = ecrnx_cfg80211_del_mpath;
4097     ecrnx_cfg80211_ops.change_mpath = ecrnx_cfg80211_change_mpath;
4098     ecrnx_cfg80211_ops.get_mpath = ecrnx_cfg80211_get_mpath;
4099     ecrnx_cfg80211_ops.dump_mpath = ecrnx_cfg80211_dump_mpath;
4100 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
4101     ecrnx_cfg80211_ops.get_mpp = ecrnx_cfg80211_get_mpp;
4102     ecrnx_cfg80211_ops.dump_mpp = ecrnx_cfg80211_dump_mpp;
4103 #endif
4104     ecrnx_cfg80211_ops.get_mesh_config = ecrnx_cfg80211_get_mesh_config;
4105     ecrnx_cfg80211_ops.update_mesh_config = ecrnx_cfg80211_update_mesh_config;
4106     ecrnx_cfg80211_ops.join_mesh = ecrnx_cfg80211_join_mesh;
4107     ecrnx_cfg80211_ops.leave_mesh = ecrnx_cfg80211_leave_mesh;
4108
4109     wiphy->flags |= (WIPHY_FLAG_MESH_AUTH | WIPHY_FLAG_IBSS_RSN);
4110 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
4111     wiphy->features |= NL80211_FEATURE_USERSPACE_MPM;
4112 #endif
4113     wiphy->interface_modes |= BIT(NL80211_IFTYPE_MESH_POINT);
4114
4115     ecrnx_limits[0].types |= BIT(NL80211_IFTYPE_MESH_POINT);
4116     ecrnx_limits_dfs[0].types |= BIT(NL80211_IFTYPE_MESH_POINT);
4117 }
4118
4119 int ecrnx_get_cal_result(struct ecrnx_hw *ecrnx_hw)
4120 {
4121         int ret;
4122         wifi_cal_data_t *result = &cal_result;
4123
4124         ret = ecrnx_send_cal_result_get_req(ecrnx_hw, result);
4125
4126         return ret;
4127 }
4128
4129 void ecrnx_he_init(void)
4130 {
4131     ecrnx_he_cap.has_he = true;
4132     memset(&ecrnx_he_cap.he_cap_elem, 0, sizeof(struct ieee80211_he_cap_elem));
4133
4134     ecrnx_he_cap.he_mcs_nss_supp.rx_mcs_80 = cpu_to_le16(0xfffa);
4135     ecrnx_he_cap.he_mcs_nss_supp.tx_mcs_80 = cpu_to_le16(0xfffa);
4136     ecrnx_he_cap.he_mcs_nss_supp.rx_mcs_160 = cpu_to_le16(0xffff);
4137     ecrnx_he_cap.he_mcs_nss_supp.tx_mcs_160 = cpu_to_le16(0xffff);
4138     ecrnx_he_cap.he_mcs_nss_supp.rx_mcs_80p80 = cpu_to_le16(0xffff);
4139     ecrnx_he_cap.he_mcs_nss_supp.tx_mcs_80p80 = cpu_to_le16(0xffff);
4140     memset(ecrnx_he_cap.ppe_thres, 0, sizeof(u8)*IEEE80211_HE_PPE_THRES_MAX_LEN);
4141 }
4142
4143 /**
4144  *
4145  */
4146 bool register_drv_done = false;
4147 int ecrnx_cfg80211_init(void *ecrnx_plat, void **platform_data)
4148 {
4149     struct ecrnx_hw *ecrnx_hw;
4150     int ret = 0;
4151     struct wiphy *wiphy;
4152     struct wireless_dev *wdev;
4153     int i;
4154
4155     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
4156     /* create a new wiphy for use with cfg80211 */
4157     wiphy = wiphy_new(&ecrnx_cfg80211_ops, sizeof(struct ecrnx_hw));
4158
4159     if (!wiphy) {
4160         dev_err(ecrnx_platform_get_dev(ecrnx_plat), "Failed to create new wiphy\n");
4161         ret = -ENOMEM;
4162         goto err_out;
4163     }
4164
4165     ecrnx_hw = wiphy_priv(wiphy);
4166     ecrnx_hw->wiphy = wiphy;
4167     ecrnx_hw->plat = ecrnx_plat;
4168     ecrnx_hw->dev = ecrnx_platform_get_dev(ecrnx_plat);
4169     ecrnx_hw->mod_params = &ecrnx_mod_params;
4170     ecrnx_hw->tcp_pacing_shift = 7;
4171     *platform_data = ecrnx_hw;
4172
4173     /* set device pointer for wiphy */
4174     set_wiphy_dev(wiphy, ecrnx_hw->dev);
4175     /* Create cache to allocate sw_txhdr */
4176     ecrnx_hw->sw_txhdr_cache = KMEM_CACHE(ecrnx_sw_txhdr, 0);
4177     if (!ecrnx_hw->sw_txhdr_cache) {
4178         wiphy_err(wiphy, "Cannot allocate cache for sw TX header\n");
4179         ret = -ENOMEM;
4180         goto err_cache;
4181     }
4182
4183     if ((ret = ecrnx_parse_configfile(ecrnx_hw, ECRNX_CONFIG_FW_NAME))) {
4184         wiphy_err(wiphy, "ecrnx_parse_configfile failed\n");
4185         goto err_config;
4186     }
4187
4188     ecrnx_hw->vif_started = 0;
4189     ecrnx_hw->monitor_vif = ECRNX_INVALID_VIF;
4190
4191     ecrnx_hw->scan_ie.addr = NULL;
4192
4193     for (i = 0; i < NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX; i++)
4194         ecrnx_hw->avail_idx_map |= BIT(i);
4195
4196     ecrnx_hwq_init(ecrnx_hw);
4197     ecrnx_txq_prepare(ecrnx_hw);
4198
4199     ecrnx_mu_group_init(ecrnx_hw);
4200
4201     /* Initialize RoC element pointer to NULL, indicate that RoC can be started */
4202     ecrnx_hw->roc = NULL;
4203     /* Cookie can not be 0 */
4204     ecrnx_hw->roc_cookie = 1;
4205
4206     wiphy->mgmt_stypes = ecrnx_default_mgmt_stypes;
4207
4208     wiphy->bands[NL80211_BAND_2GHZ] = &ecrnx_band_2GHz;
4209 #ifdef CONFIG_ECRNX_5G
4210     wiphy->bands[NL80211_BAND_5GHZ] = &ecrnx_band_5GHz;
4211 #endif
4212     wiphy->interface_modes =
4213         BIT(NL80211_IFTYPE_STATION)     |
4214         BIT(NL80211_IFTYPE_AP)          |
4215         BIT(NL80211_IFTYPE_AP_VLAN)     |
4216         BIT(NL80211_IFTYPE_P2P_CLIENT)  |
4217         BIT(NL80211_IFTYPE_P2P_GO)      |
4218         BIT(NL80211_IFTYPE_MONITOR);
4219     wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
4220 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
4221         WIPHY_FLAG_HAS_CHANNEL_SWITCH |
4222 #endif
4223         WIPHY_FLAG_4ADDR_STATION |
4224         WIPHY_FLAG_4ADDR_AP;
4225 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
4226     wiphy->max_num_csa_counters = BCN_MAX_CSA_CPT;
4227 #endif
4228
4229     wiphy->max_remain_on_channel_duration = ecrnx_hw->mod_params->roc_dur_max;
4230
4231 #if 0 /* eswin:rm the feature of OBSS_SCAN which can cause the uplink stream shutdown */
4232     wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN |
4233         NL80211_FEATURE_SK_TX_STATUS |
4234 #else
4235     wiphy->features |= NL80211_FEATURE_SK_TX_STATUS |
4236 #endif
4237         NL80211_FEATURE_VIF_TXPOWER |
4238 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
4239         NL80211_FEATURE_ACTIVE_MONITOR |
4240 #endif
4241 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
4242         NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
4243 #endif
4244         0;
4245
4246 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
4247     wiphy->features |= NL80211_FEATURE_SAE;
4248 #endif
4249
4250 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0)
4251     ecrnx_he_init();
4252 #endif
4253
4254     if (ecrnx_mod_params.tdls)
4255         /* TDLS support */
4256         wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
4257
4258     wiphy->iface_combinations   = ecrnx_combinations;
4259     /* -1 not to include combination with radar detection, will be re-added in
4260        ecrnx_handle_dynparams if supported */
4261     wiphy->n_iface_combinations = ARRAY_SIZE(ecrnx_combinations) - 1;
4262     wiphy->reg_notifier = ecrnx_reg_notifier;
4263
4264     wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
4265
4266     wiphy->cipher_suites = cipher_suites;
4267     wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites) - NB_RESERVED_CIPHER;
4268
4269     ecrnx_hw->ext_capa[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING;
4270     ecrnx_hw->ext_capa[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT;
4271     ecrnx_hw->ext_capa[4] = WLAN_EXT_CAPA5_QOS_MAP_SUPPORT;
4272 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
4273     ecrnx_hw->ext_capa[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF;
4274     wiphy->extended_capabilities = ecrnx_hw->ext_capa;
4275     wiphy->extended_capabilities_mask = ecrnx_hw->ext_capa;
4276     wiphy->extended_capabilities_len = ARRAY_SIZE(ecrnx_hw->ext_capa);
4277 #endif
4278
4279 #ifndef CONFIG_ECRNX_ESWIN
4280     tasklet_init(&ecrnx_hw->task, ecrnx_task, (unsigned long)ecrnx_hw);
4281 #endif
4282
4283     INIT_LIST_HEAD(&ecrnx_hw->vifs);
4284 #ifdef CONFIG_ECRNX_ESWIN
4285     INIT_LIST_HEAD(&ecrnx_hw->agg_rx_list);
4286     INIT_LIST_HEAD(&ecrnx_hw->defrag_rx_list);
4287 #endif
4288
4289     mutex_init(&ecrnx_hw->dbgdump_elem.mutex);
4290     spin_lock_init(&ecrnx_hw->tx_lock);
4291     spin_lock_init(&ecrnx_hw->cb_lock);
4292     spin_lock_init(&ecrnx_hw->rx_lock);
4293     spin_lock_init(&ecrnx_hw->scan_req_lock);
4294     spin_lock_init(&ecrnx_hw->connect_req_lock);
4295
4296     if ((ret = ecrnx_platform_on(ecrnx_hw, NULL)))
4297         goto err_platon;
4298
4299         if ((ret = ecrnx_get_cal_result(ecrnx_hw))) {
4300         wiphy_err(wiphy, "get cal result failed\n");
4301         goto err_lmac_reqs;
4302         } else {
4303                 if ((0 == (cal_result.mac_addr[0] & 0x1)) && (cal_result.mac_addr[0] || cal_result.mac_addr[1] 
4304                         || cal_result.mac_addr[2] || cal_result.mac_addr[3] || cal_result.mac_addr[4] 
4305                         || cal_result.mac_addr[5])) {
4306                         memcpy(ecrnx_hw->conf_param.mac_addr, cal_result.mac_addr, ETH_ALEN);
4307                 }
4308         }
4309         memcpy(wiphy->perm_addr, ecrnx_hw->conf_param.mac_addr, ETH_ALEN);
4310
4311     /* Reset FW */
4312     if ((ret = ecrnx_send_reset(ecrnx_hw)))
4313         goto err_lmac_reqs;
4314     if ((ret = ecrnx_send_version_req(ecrnx_hw, &ecrnx_hw->version_cfm)))
4315         goto err_lmac_reqs;
4316     ecrnx_set_vers(ecrnx_hw);
4317
4318     if ((ret = ecrnx_handle_dynparams(ecrnx_hw, ecrnx_hw->wiphy)))
4319         goto err_lmac_reqs;
4320
4321     ecrnx_enable_mesh(ecrnx_hw);
4322     ecrnx_radar_detection_init(&ecrnx_hw->radar);
4323
4324 #ifdef CONFIG_ECRNX_P2P
4325         ecrnx_p2p_listen_init(&ecrnx_hw->p2p_listen);
4326 #endif
4327
4328     /* Set parameters to firmware */
4329     ecrnx_send_me_config_req(ecrnx_hw);
4330
4331     /* Only monitor mode supported when custom channels are enabled */
4332     if (ecrnx_mod_params.custchan) {
4333         ecrnx_limits[0].types = BIT(NL80211_IFTYPE_MONITOR);
4334         ecrnx_limits_dfs[0].types = BIT(NL80211_IFTYPE_MONITOR);
4335     }
4336
4337     if ((ret = wiphy_register(wiphy))) {
4338         wiphy_err(wiphy, "Could not register wiphy device\n");
4339         goto err_register_wiphy;
4340     }
4341
4342     INIT_WORK(&ecrnx_hw->defer_rx.work, ecrnx_rx_deferred);
4343     skb_queue_head_init(&ecrnx_hw->defer_rx.sk_list);
4344     /* Update regulatory (if needed) and set channel parameters to firmware
4345        (must be done after WiPHY registration) */
4346     ecrnx_fw_log_level_set((u32)ecrnx_hw->conf_param.fw_log_level, (u32)ecrnx_hw->conf_param.fw_log_type);
4347     ecrnx_custregd(ecrnx_hw, wiphy);
4348     ecrnx_send_me_chan_config_req(ecrnx_hw);
4349
4350     /* config gain delta */
4351     ecrnx_send_set_gain_delta_req(ecrnx_hw);
4352
4353 #ifdef CONFIG_ECRNX_DEBUGFS
4354     if ((ret = ecrnx_dbgfs_register(ecrnx_hw, "ecrnx"))) {
4355                 ECRNX_DBG(" ecrnx_dbgfs_register error \n");
4356         wiphy_err(wiphy, "Failed to register debugfs entries");
4357         goto err_debugfs;
4358     }
4359 #endif
4360
4361     rtnl_lock();
4362
4363     /* Add an initial interface */
4364     wdev = ecrnx_interface_add(ecrnx_hw, "wlan%d", NET_NAME_UNKNOWN,
4365                ecrnx_mod_params.custchan ? NL80211_IFTYPE_MONITOR : NL80211_IFTYPE_STATION,
4366                NULL);
4367 #if defined(CONFIG_ECRNX_P2P)
4368     wdev = ecrnx_interface_add(ecrnx_hw, "p2p%d", NET_NAME_UNKNOWN, NL80211_IFTYPE_STATION,
4369                NULL);
4370 #endif
4371     rtnl_unlock();
4372
4373     if (!wdev) {
4374         wiphy_err(wiphy, "Failed to instantiate a network device\n");
4375         ret = -ENOMEM;
4376         goto err_add_interface;
4377     }
4378
4379     wiphy_info(wiphy, "New interface create %s", wdev->netdev->name);
4380
4381 #if defined(CONFIG_ECRNX_DEBUGFS_CUSTOM)
4382     ecrnx_debugfs_init(ecrnx_hw);
4383 #endif
4384     register_drv_done = true;
4385     return 0;
4386
4387 err_add_interface:
4388 #ifdef CONFIG_ECRNX_DEBUGFS
4389 err_debugfs:
4390 #endif
4391     wiphy_unregister(ecrnx_hw->wiphy);
4392 err_register_wiphy:
4393 err_lmac_reqs:
4394     ecrnx_fw_trace_dump(ecrnx_hw);
4395     ecrnx_platform_off(ecrnx_hw, NULL);
4396 err_platon:
4397 err_config:
4398     kmem_cache_destroy(ecrnx_hw->sw_txhdr_cache);
4399 err_cache:
4400     wiphy_free(wiphy);
4401 err_out:
4402     ECRNX_DBG(" %s cfg80211 init failed %d!!", __func__, ret);
4403     return ret;
4404 }
4405
4406 /**
4407  *
4408  */
4409 void ecrnx_cfg80211_deinit(struct ecrnx_hw *ecrnx_hw)
4410 {
4411     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
4412     if(!register_drv_done)
4413     {
4414         return;
4415     }
4416 #if 0
4417     ecrnx_dbgfs_unregister(ecrnx_hw);
4418 #endif
4419     register_drv_done = false;
4420
4421     del_timer_sync(&ecrnx_hw->txq_cleanup);
4422     ecrnx_wdev_unregister(ecrnx_hw);
4423     if(ecrnx_hw->wiphy)
4424     {
4425         ECRNX_DBG("%s wiphy_unregister \n", __func__);
4426         wiphy_unregister(ecrnx_hw->wiphy);
4427         wiphy_free(ecrnx_hw->wiphy);
4428         ecrnx_hw->wiphy = NULL;
4429     }
4430     ecrnx_radar_detection_deinit(&ecrnx_hw->radar);
4431     ecrnx_platform_off(ecrnx_hw, NULL);
4432     kmem_cache_destroy(ecrnx_hw->sw_txhdr_cache);
4433 }
4434
4435 /**
4436  *
4437  */
4438 static int __init ecrnx_mod_init(void)
4439 {
4440     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
4441     ecrnx_print_version();
4442     return ecrnx_platform_register_drv();
4443 }
4444
4445 /**
4446  *
4447  */
4448 static void __exit ecrnx_mod_exit(void)
4449 {
4450     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
4451
4452 #if defined(CONFIG_ECRNX_DEBUGFS_CUSTOM)
4453     ecrnx_debugfs_exit();
4454 #endif
4455
4456     ecrnx_platform_unregister_drv();
4457 }
4458
4459 module_init(ecrnx_mod_init);
4460 module_exit(ecrnx_mod_exit);
4461
4462 MODULE_FIRMWARE(ECRNX_CONFIG_FW_NAME);
4463
4464 MODULE_DESCRIPTION(RW_DRV_DESCRIPTION);
4465 MODULE_VERSION(ECRNX_VERS_MOD);
4466 MODULE_AUTHOR(RW_DRV_COPYRIGHT " " RW_DRV_AUTHOR);
4467 MODULE_LICENSE("GPL");