2 ******************************************************************************
6 * @brief Entry point of the ECRNX driver
8 * Copyright (C) ESWIN 2015-2020
10 ******************************************************************************
13 #include <linux/module.h>
14 #include <linux/pci.h>
15 #include <linux/inetdevice.h>
16 #include <net/cfg80211.h>
18 #include <linux/etherdevice.h>
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>
25 #include "ecrnx_msg_tx.h"
27 #include "reg_access.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"
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"
48 static struct ieee80211_rate ecrnx_ratetable[] = {
50 RATE(20, 0x01, IEEE80211_RATE_SHORT_PREAMBLE),
51 RATE(55, 0x02, IEEE80211_RATE_SHORT_PREAMBLE),
52 RATE(110, 0x03, IEEE80211_RATE_SHORT_PREAMBLE),
63 /* The channels indexes here are not used anymore */
64 static struct ieee80211_channel ecrnx_2ghz_channels[] = {
79 // Extra channels defined only to be used for PHY measures.
80 // Enabled only if custregd and custchan parameters are set
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
187 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
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,
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)
204 .iftype_data = &ecrnx_he_capa,
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)
220 .iftype_data = &ecrnx_he_capa,
227 static struct ieee80211_iface_limit ecrnx_limits[] = {
228 { .max = NX_VIRT_DEV_MAX, .types = BIT(NL80211_IFTYPE_AP) |
229 BIT(NL80211_IFTYPE_STATION)}
232 static struct ieee80211_iface_limit ecrnx_limits_dfs[] = {
233 { .max = NX_VIRT_DEV_MAX, .types = BIT(NL80211_IFTYPE_AP)}
236 static const struct ieee80211_iface_combination ecrnx_combinations[] = {
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,
243 /* Keep this combination as the last one */
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)),
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] = {
263 .rx = (BIT(IEEE80211_STYPE_ACTION >> 4) |
264 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
265 BIT(IEEE80211_STYPE_AUTH >> 4)),
267 [NL80211_IFTYPE_AP] = {
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)),
277 [NL80211_IFTYPE_AP_VLAN] = {
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)),
288 [NL80211_IFTYPE_P2P_CLIENT] = {
290 .rx = (BIT(IEEE80211_STYPE_ACTION >> 4) |
291 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)),
293 [NL80211_IFTYPE_P2P_GO] = {
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)),
303 [NL80211_IFTYPE_P2P_DEVICE] = {
305 .rx = (BIT(IEEE80211_STYPE_ACTION >> 4) |
306 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)),
308 [NL80211_IFTYPE_MESH_POINT] = {
310 .rx = (BIT(IEEE80211_STYPE_ACTION >> 4) |
311 BIT(IEEE80211_STYPE_AUTH >> 4) |
312 BIT(IEEE80211_STYPE_DEAUTH >> 4)),
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
328 #define NB_RESERVED_CIPHER 5;
330 static const int ecrnx_ac2hwq[1][NL80211_NUM_ACS] = {
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
339 const int ecrnx_tid2hwq[IEEE80211_NUM_TIDS] = {
348 /* TID_8 is used for management frames */
350 /* At the moment, all others TID are mapped to BE */
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,
367 /*********************************************************************
369 *********************************************************************/
370 struct ecrnx_sta *ecrnx_get_sta(struct ecrnx_hw *ecrnx_hw, const u8 *mac_addr)
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))
383 void ecrnx_enable_wapi(struct ecrnx_hw *ecrnx_hw)
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;
390 void ecrnx_enable_mfp(struct ecrnx_hw *ecrnx_hw)
392 cipher_suites[ecrnx_hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_AES_CMAC;
393 ecrnx_hw->wiphy->n_cipher_suites ++;
396 void ecrnx_enable_gcmp(struct ecrnx_hw *ecrnx_hw)
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;
404 u8 *ecrnx_build_bcn(struct ecrnx_bcn *bcn, struct cfg80211_beacon_data *new)
409 u8 *head = kmalloc(new->head_len, GFP_KERNEL);
418 bcn->head_len = new->head_len;
419 memcpy(bcn->head, new->head, new->head_len);
422 u8 *tail = kmalloc(new->tail_len, GFP_KERNEL);
431 bcn->tail_len = new->tail_len;
432 memcpy(bcn->tail, new->tail, new->tail_len);
439 bcn->len = bcn->head_len + bcn->tail_len + bcn->ies_len + bcn->tim_len;
441 buf = kmalloc(bcn->len, GFP_KERNEL);
445 // Build the beacon buffer
447 memcpy(pos, bcn->head, bcn->head_len);
448 pos += bcn->head_len;
449 *pos++ = WLAN_EID_TIM;
456 memcpy(pos, bcn->tail, bcn->tail_len);
457 pos += bcn->tail_len;
460 memcpy(pos, bcn->ies, bcn->ies_len);
467 static void ecrnx_del_bcn(struct ecrnx_bcn *bcn)
492 * Link channel ctxt to a vif and thus increments count for this context.
494 void ecrnx_chanctx_link(struct ecrnx_vif *vif, u8 ch_idx,
495 struct cfg80211_chan_def *chandef)
497 struct ecrnx_chanctx *ctxt;
499 if (ch_idx >= NX_CHAN_CTXT_CNT) {
500 WARN(1, "Invalid channel ctxt id %d", ch_idx);
504 vif->ch_index = ch_idx;
505 ctxt = &vif->ecrnx_hw->chanctx_table[ch_idx];
508 // For now chandef is NULL for STATION interface
510 if (!ctxt->chan_def.chan)
511 ctxt->chan_def = *chandef;
513 // TODO. check that chandef is the same as the one already
520 * Unlink channel ctxt from a vif and thus decrements count for this context
522 void ecrnx_chanctx_unlink(struct ecrnx_vif *vif)
524 struct ecrnx_chanctx *ctxt;
526 if (vif->ch_index == ECRNX_CH_NOT_SET)
529 ctxt = &vif->ecrnx_hw->chanctx_table[vif->ch_index];
531 if (ctxt->count == 0) {
532 WARN(1, "Chan ctxt ref count is already 0");
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,
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;
549 vif->ch_index = ECRNX_CH_NOT_SET;
552 int ecrnx_chanctx_valid(struct ecrnx_hw *ecrnx_hw, u8 ch_idx)
554 if (ch_idx >= NX_CHAN_CTXT_CNT ||
555 ecrnx_hw->chanctx_table[ch_idx].chan_def.chan == NULL) {
562 static void ecrnx_del_csa(struct ecrnx_vif *vif)
564 struct ecrnx_hw *ecrnx_hw = vif->ecrnx_hw;
565 struct ecrnx_csa *csa = vif->ap.csa;
570 ecrnx_ipc_elem_var_deallocs(ecrnx_hw, &csa->elem);
571 ecrnx_del_bcn(&csa->bcn);
576 static void ecrnx_csa_finish(struct work_struct *ws)
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;
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);
589 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
590 cfg80211_stop_iface(ecrnx_hw->wiphy, &vif->wdev, GFP_KERNEL);
592 cfg80211_disconnected(vif->ndev, 0, NULL, 0, 0, GFP_KERNEL);
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);
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);
615 * ecrnx_external_auth_enable - Enable external authentication on a vif
617 * @vif: VIF on which external authentication must be enabled
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.
623 void ecrnx_external_auth_enable(struct ecrnx_vif *vif)
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);
631 * ecrnx_external_auth_disable - Disable external authentication on a vif
633 * @vif: VIF on which external authentication must be disabled
635 void ecrnx_external_auth_disable(struct ecrnx_vif *vif)
637 if (!(vif->sta.flags & ECRNX_STA_EXT_AUTH))
640 vif->sta.flags &= ~ECRNX_STA_EXT_AUTH;
641 ecrnx_txq_unk_vif_deinit(vif);
645 * ecrnx_update_mesh_power_mode -
647 * @vif: mesh VIF for which power mode is updated
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.
655 * If there is no link then the power mode for next peer is used;
657 void ecrnx_update_mesh_power_mode(struct ecrnx_vif *vif)
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;
666 if (ECRNX_VIF_TYPE(vif) != NL80211_IFTYPE_MESH_POINT)
669 if (list_empty(&vif->ap.sta_list)) {
670 mesh_pm = vif->ap.next_mesh_pm;
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;
680 if (mesh_pm == vif->ap.mesh_pm)
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) ||
689 vif->ap.mesh_pm = mesh_pm;
693 void ecrnx_save_assoc_info_for_ft(struct ecrnx_vif *vif,
694 struct cfg80211_connect_params *sme)
696 int ies_len = sme->ie_len + sme->ssid_len + 2;
698 if (!vif->sta.ft_assoc_ies) {
699 if (!cfg80211_find_ie(WLAN_EID_MOBILITY_DOMAIN, sme->ie, sme->ie_len))
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);
707 if (!vif->sta.ft_assoc_ies)
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;
718 * ecrnx_rsne_to_connect_params - Initialise cfg80211_connect_params from
722 * @sme: Structure cfg80211_connect_params to initialize
724 * The goal is only to initialize enough for ecrnx_send_sm_connect_req
726 int ecrnx_rsne_to_connect_params(const struct ecrnx_element *rsne,
727 struct cfg80211_connect_params *sme)
729 int len = rsne->datalen;
731 const u8 *pos = rsne->data ;
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);
740 sme->crypto.cipher_group = ntohl(*((u32 *)pos));
742 clen = le16_to_cpu(*((u16 *)pos)) * 4;
747 // only need one cipher suite
748 sme->crypto.n_ciphers_pairwise = 1;
749 sme->crypto.ciphers_pairwise[0] = ntohl(*((u32 *)pos));
754 clen = le16_to_cpu(*((u16 *)pos)) * 4;
766 clen = le16_to_cpu(*((u16 *)pos)) * 16;
768 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
770 sme->mfp = NL80211_MFP_REQUIRED;
776 /*********************************************************************
778 ********************************************************************/
780 * int (*ndo_open)(struct net_device *dev);
781 * This function is called when network device transistions to the up
784 * - Start FW if this is the first interface opened
785 * - Add interface at fw level
787 static int ecrnx_open(struct net_device *dev)
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;
794 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
796 // Check if it is the first opened VIF
797 if (ecrnx_hw->vif_started == 0)
800 if ((error = ecrnx_send_start(ecrnx_hw)))
803 /* Device is now started */
804 set_bit(ECRNX_DEV_STARTED, &ecrnx_hw->flags);
808 netdev_info(dev, "Started repeatedly");
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);
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)))
824 if (add_if_cfm.status != 0) {
825 ECRNX_PRINT_CFM_ERR(add_if);
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);
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,
849 netif_carrier_off(dev);
855 * int (*ndo_stop)(struct net_device *dev);
856 * This function is called when network device transistions to the down
859 * - Remove interface at fw level
860 * - Reset FW if this is the last interface opened
862 static int ecrnx_close(struct net_device *dev)
864 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
865 struct ecrnx_hw *ecrnx_hw = ecrnx_vif->ecrnx_hw;
867 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
869 netdev_info(dev, "CLOSE");
871 ecrnx_radar_cancel_cac(&ecrnx_hw->radar);
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 = {
882 cfg80211_scan_done(ecrnx_hw->scan_request, &info);
884 cfg80211_scan_done(ecrnx_hw->scan_request, true);
886 ecrnx_hw->scan_request = NULL;
889 spin_unlock_bh(&ecrnx_hw->scan_req_lock);
890 ecrnx_send_remove_if(ecrnx_hw, ecrnx_vif->vif_index);
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;
898 /* Ensure that we won't process disconnect ind */
899 spin_lock_bh(&ecrnx_hw->cb_lock);
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;
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);
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);
921 netdev_warn(dev, "AP not stopped when disabling interface");
925 ecrnx_hw->vif_table[ecrnx_vif->vif_index] = NULL;
926 spin_unlock_bh(&ecrnx_hw->cb_lock);
928 ecrnx_chanctx_unlink(ecrnx_vif);
930 if (ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_MONITOR)
931 ecrnx_hw->monitor_vif = ECRNX_INVALID_VIF;
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);
939 ecrnx_send_reset(ecrnx_hw);
941 // Set parameters to firmware
942 ecrnx_send_me_config_req(ecrnx_hw);
944 // Set channel parameters to firmware
945 ecrnx_send_me_chan_config_req(ecrnx_hw);
947 clear_bit(ECRNX_DEV_STARTED, &ecrnx_hw->flags);
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
966 static struct net_device_stats *ecrnx_get_stats(struct net_device *dev)
968 struct ecrnx_vif *vif = netdev_priv(dev);
970 return &vif->net_stats;
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
979 u16 ecrnx_select_queue(struct net_device *dev, struct sk_buff *skb,
980 struct net_device *sb_dev)
982 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
983 return ecrnx_select_txq(ecrnx_vif, skb);
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.
992 static int ecrnx_set_mac_address(struct net_device *dev, void *addr)
994 struct sockaddr *sa = addr;
997 ret = eth_mac_addr(dev, sa);
1002 int ecrnx_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1004 //struct iwreq *wrq = (struct iwreq *)rq;
1008 case (SIOCDEVPRIVATE+1):
1009 //ret = ecrnx_android_priv_cmd(dev, rq, cmd);
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,
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,
1038 #ifdef CONFIG_WIRELESS_EXT
1039 extern const struct iw_handler_def ecrnx_wext_handler_def;
1042 static void ecrnx_netdev_setup(struct net_device *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;
1050 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
1051 dev->destructor = free_netdev;
1053 dev->needs_free_netdev = true;
1055 dev->watchdog_timeo = ECRNX_TX_LIFETIME_MS;
1056 dev->needed_headroom = ECRNX_TX_MAX_HEADROOM;
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 */
1065 dev->hw_features = 0;
1068 /*********************************************************************
1069 * Cfg80211 callbacks (and helper)
1070 *********************************************************************/
1071 static struct wireless_dev *ecrnx_interface_add(struct ecrnx_hw *ecrnx_hw,
1073 unsigned char name_assign_type,
1074 enum nl80211_iftype type,
1075 struct vif_params *params)
1077 struct net_device *ndev;
1078 struct ecrnx_vif *vif;
1079 int min_idx, max_idx;
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;
1089 max_idx = NX_VIRT_DEV_MAX;
1092 for (i = min_idx; i < max_idx; i++) {
1093 if ((ecrnx_hw->avail_idx_map) & BIT(i)) {
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");
1113 ndev = alloc_netdev_mqs(sizeof(*vif), name, name_assign_type,
1114 ecrnx_netdev_setup, NX_NB_NDEV_TXQ, 1);
1118 vif = netdev_priv(ndev);
1119 ndev->ieee80211_ptr = &vif->wdev;
1120 vif->wdev.wiphy = ecrnx_hw->wiphy;
1121 vif->ecrnx_hw = ecrnx_hw;
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;
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));
1134 case NL80211_IFTYPE_STATION:
1135 case NL80211_IFTYPE_P2P_CLIENT:
1138 vif->sta.tdls_sta = NULL;
1139 vif->sta.ft_assoc_ies = NULL;
1140 vif->sta.ft_assoc_ies_len = 0;
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;
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));
1156 case NL80211_IFTYPE_AP_VLAN:
1158 struct ecrnx_vif *master_vif;
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,
1175 vif->ap_vlan.master = master_vif;
1176 vif->ap_vlan.sta_4a = NULL;
1179 case NL80211_IFTYPE_MONITOR:
1180 ndev->type = ARPHRD_IEEE80211_RADIOTAP;
1181 ndev->netdev_ops = &ecrnx_netdev_monitor_ops;
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);
1193 memcpy(ndev->dev_addr, ecrnx_hw->wiphy->perm_addr, ETH_ALEN);
1194 ndev->dev_addr[5] ^= vif_idx;
1198 vif->use_4addr = params->use_4addr;
1199 ndev->ieee80211_ptr->use_4addr = params->use_4addr;
1201 vif->use_4addr = false;
1204 if (register_netdevice(ndev))
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);
1212 //#if defined(CONFIG_ECRNX_ESWIN_SDIO) || defined(CONFIG_ECRNX_ESWIN_USB)
1213 init_waitqueue_head(&vif->rxdataq);
1225 * @brief Retrieve the ecrnx_sta object allocated for a given MAC address
1228 static struct ecrnx_sta *ecrnx_retrieve_sta(struct ecrnx_hw *ecrnx_hw,
1229 struct ecrnx_vif *ecrnx_vif, u8 *addr,
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);
1238 /* Check if the packet is bufferable or not */
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];
1246 if (ecrnx_sta->valid)
1249 /* Returned STA pointer */
1250 struct ecrnx_sta *ecrnx_sta;
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 */
1263 return ecrnx_vif->sta.ap;
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.
1276 static struct wireless_dev *ecrnx_cfg80211_add_iface(struct wiphy *wiphy,
1278 unsigned char name_assign_type,
1279 enum nl80211_iftype type,
1280 struct vif_params *params)
1282 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1283 struct wireless_dev *wdev;
1285 wdev = ecrnx_interface_add(ecrnx_hw, name, name_assign_type, type, params);
1288 return ERR_PTR(-EINVAL);
1294 * @del_virtual_intf: remove the virtual interface
1296 static int ecrnx_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
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);
1302 netdev_info(dev, "Remove Interface");
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);
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;
1316 /* Clear the priv in adapter */
1317 dev->ieee80211_ptr = NULL;
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,
1327 * @change_virtual_intf: change type/configuration of virtual interface,
1328 * keep the struct wireless_dev's iftype updated.
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)
1335 #ifndef CONFIG_ECRNX_MON_DATA
1336 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1338 struct ecrnx_vif *vif = netdev_priv(dev);
1341 ECRNX_PRINT("%s:dev:0x%p, type:%d, vif->up:%d \n", __func__, dev, type, vif->up);
1345 if((ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_AP) || (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_GO))
1347 ecrnx_cfg80211_stop_ap(wiphy, dev);
1349 else if((ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_STATION) || (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_CLIENT))
1351 ecrnx_cfg80211_disconnect(wiphy, dev, WLAN_REASON_DEAUTH_LEAVING);
1353 ECRNX_ERR("ecrnx_cfg80211_change_iface: -EBUSY \n");
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");
1374 // Reset to default case (i.e. not monitor)
1375 dev->type = ARPHRD_ETHER;
1376 dev->netdev_ops = &ecrnx_netdev_ops;
1379 case NL80211_IFTYPE_STATION:
1380 case NL80211_IFTYPE_P2P_CLIENT:
1383 vif->sta.tdls_sta = NULL;
1384 vif->sta.ft_assoc_ies = NULL;
1385 vif->sta.ft_assoc_ies_len = 0;
1387 case NL80211_IFTYPE_MESH_POINT:
1388 INIT_LIST_HEAD(&vif->ap.mpath_list);
1389 INIT_LIST_HEAD(&vif->ap.proxy_list);
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));
1397 case NL80211_IFTYPE_AP_VLAN:
1399 case NL80211_IFTYPE_MONITOR:
1400 dev->type = ARPHRD_IEEE80211_RADIOTAP;
1401 dev->netdev_ops = &ecrnx_netdev_monitor_ops;
1407 vif->generation = 0;
1408 vif->wdev.iftype = type;
1409 if (params->use_4addr != -1)
1410 vif->use_4addr = params->use_4addr;
1422 * Used as P2P_DEVICE mode
1424 static int ecrnx_cfg80211_start_p2p_device(struct wiphy *wiphy,
1425 struct wireless_dev *wdev)
1427 ECRNX_PRINT("rwnx_cfg80211_start_p2p_device\n");
1431 static void ecrnx_cfg80211_stop_p2p_device(struct wiphy *wiphy,
1432 struct wireless_dev *wdev)
1436 /* Used as P2P_DEVICE mode*/
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.
1445 static int ecrnx_cfg80211_scan(struct wiphy *wiphy,
1446 struct cfg80211_scan_request *request)
1448 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1449 struct ecrnx_vif *ecrnx_vif = container_of(request->wdev, struct ecrnx_vif,
1453 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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;
1464 ECRNX_PRINT("scan is already running!!\n");
1466 ECRNX_DBG("send finish:ecrnx_cfg80211_scan \n");
1471 static void ecrnx_cfg80211_abort_scan(struct wiphy *wiphy,
1472 struct wireless_dev *wdev)
1475 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1476 struct ecrnx_vif *ecrnx_vif = container_of(wdev, struct ecrnx_vif,
1479 //mutex_lock(&ecrnx_hw->mutex);
1480 ECRNX_PRINT("%s:ecrnx_hw->scan_request:0x%p \n", __func__, ecrnx_hw->scan_request);
1482 if(!ecrnx_hw->scan_request){
1483 ECRNX_ERR("no scan is running, don't need abort! \n");
1487 if(wdev->iftype != NL80211_IFTYPE_STATION){
1488 ECRNX_ERR("abort scan ignored, iftype(%d)\n", wdev->iftype);
1492 if(wdev != ecrnx_hw->scan_request->wdev){
1493 ECRNX_ERR("abort scan was called on the wrong iface\n");
1497 ret = ecrnx_send_scanu_cancel_req(ecrnx_hw, ecrnx_vif);
1500 //mutex_unlock(&ecrnx_hw->mutex);
1505 * @add_key: add a key with the given parameters. @mac_addr will be %NULL
1506 * when adding a group key.
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)
1512 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1513 struct ecrnx_vif *vif = netdev_priv(netdev);
1515 struct mm_key_add_cfm key_add_cfm;
1517 struct ecrnx_sta *sta = NULL;
1518 struct ecrnx_key *ecrnx_key;
1520 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1523 sta = ecrnx_get_sta(ecrnx_hw, mac_addr);
1526 ecrnx_key = &sta->key;
1529 ecrnx_key = &vif->key[key_index];
1531 /* Retrieve the cipher suite selector */
1532 switch (params->cipher) {
1533 case WLAN_CIPHER_SUITE_WEP40:
1534 cipher = MAC_CIPHER_WEP40;
1536 case WLAN_CIPHER_SUITE_WEP104:
1537 cipher = MAC_CIPHER_WEP104;
1539 case WLAN_CIPHER_SUITE_TKIP:
1540 cipher = MAC_CIPHER_TKIP;
1542 case WLAN_CIPHER_SUITE_CCMP:
1543 cipher = MAC_CIPHER_CCMP;
1545 case WLAN_CIPHER_SUITE_AES_CMAC:
1546 cipher = MAC_CIPHER_BIP_CMAC_128;
1548 case WLAN_CIPHER_SUITE_SMS4:
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++) {
1555 key[i] = key[WPI_SUBKEY_LEN - 1 - i];
1556 key[WPI_SUBKEY_LEN - 1 - i] = tmp;
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;
1565 case WLAN_CIPHER_SUITE_GCMP:
1566 cipher = MAC_CIPHER_GCMP_128;
1568 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
1569 case WLAN_CIPHER_SUITE_GCMP_256:
1570 cipher = MAC_CIPHER_GCMP_256;
1572 case WLAN_CIPHER_SUITE_CCMP_256:
1573 cipher = MAC_CIPHER_CCMP_256;
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)))
1586 if (key_add_cfm.status != 0) {
1587 ECRNX_PRINT_CFM_ERR(key_add);
1591 /* Save the index retrieved from LMAC */
1592 ecrnx_key->hw_idx = key_add_cfm.hw_key_idx;
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.
1605 static int ecrnx_cfg80211_get_key(struct wiphy *wiphy, struct net_device *netdev,
1606 u8 key_index, bool pairwise, const u8 *mac_addr,
1608 void (*callback)(void *cookie, struct key_params*))
1610 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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.
1620 static int ecrnx_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
1621 u8 key_index, bool pairwise, const u8 *mac_addr)
1623 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1624 struct ecrnx_vif *vif = netdev_priv(netdev);
1626 struct ecrnx_sta *sta = NULL;
1627 struct ecrnx_key *ecrnx_key;
1629 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1631 sta = ecrnx_get_sta(ecrnx_hw, mac_addr);
1634 ecrnx_key = &sta->key;
1637 ecrnx_key = &vif->key[key_index];
1639 error = ecrnx_send_key_del(ecrnx_hw, ecrnx_key->hw_idx);
1645 * @set_default_key: set the default key on an interface
1647 static int ecrnx_cfg80211_set_default_key(struct wiphy *wiphy,
1648 struct net_device *netdev,
1649 u8 key_index, bool unicast, bool multicast)
1651 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1657 * @set_default_mgmt_key: set the default management frame key on an interface
1659 static int ecrnx_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,
1660 struct net_device *netdev,
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)
1673 static int ecrnx_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
1674 struct cfg80211_connect_params *sme)
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;
1681 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1683 /* For SHARED-KEY authentication, must install key first */
1684 if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY && sme->key)
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);
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");
1702 /* Forward the information to the LMAC */
1703 if ((error = ecrnx_send_sm_connect_req(ecrnx_hw, ecrnx_vif, sme, &sm_connect_cfm)))
1705 ECRNX_PRINT("%s:bssid:%pM, send status:%d\n", __func__, sme->bssid, sm_connect_cfm.status);
1708 switch (sm_connect_cfm.status)
1711 ecrnx_save_assoc_info_for_ft(ecrnx_vif, sme);
1715 error = -EINPROGRESS;
1720 case CO_OP_IN_PROGRESS:
1732 * @disconnect: Disconnect from the BSS/ESS.
1733 * (invoked with the wireless_dev mutex held)
1735 static int ecrnx_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
1738 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1739 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
1741 ECRNX_PRINT("%s:dev:0x%p, vif_index:%d, reason_code:%d \n", __func__, dev, ecrnx_vif->vif_index, reason_code);
1743 return(ecrnx_send_sm_disconnect_req(ecrnx_hw, ecrnx_vif, reason_code));
1746 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
1748 * @external_auth: indicates result of offloaded authentication processing from
1751 static int ecrnx_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *dev,
1752 struct cfg80211_external_auth_params *params)
1754 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
1755 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
1757 if (!(ecrnx_vif->sta.flags & ECRNX_STA_EXT_AUTH))
1760 ecrnx_external_auth_disable(ecrnx_vif);
1761 return ecrnx_send_sm_external_auth_required_rsp(ecrnx_hw, ecrnx_vif,
1767 * @add_station: Add a new station.
1769 static int ecrnx_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
1770 const u8 *mac, struct station_parameters *params)
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;
1777 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1779 WARN_ON(ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_AP_VLAN);
1781 /* Do not add TDLS station */
1782 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
1785 /* Indicate we are in a STA addition process - This will allow handling
1786 * potential PS mode change indications correctly
1788 set_bit(ECRNX_DEV_ADDING_STA, &ecrnx_hw->flags);
1790 /* Forward the information to the LMAC */
1791 if ((error = ecrnx_send_me_sta_add(ecrnx_hw, params, mac, ecrnx_vif->vif_index,
1796 switch (me_sta_add_cfm.status)
1800 struct ecrnx_sta *sta = &ecrnx_hw->sta_table[me_sta_add_cfm.sta_idx];
1802 ECRNX_PRINT("%s-%d:sta:0x%p, sta_idx:%d \n", __func__, __LINE__, sta, me_sta_add_cfm.sta_idx);
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;
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;
1819 sta->mesh_pm = ecrnx_vif->ap.next_mesh_pm;
1821 ecrnx_update_mesh_power_mode(ecrnx_vif);
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;
1828 sta->uapsd_tids &= ~(1 << tid);
1830 memcpy(sta->mac_addr, mac, ETH_ALEN);
1831 ecrnx_dbgfs_register_sta(ecrnx_hw, sta);
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++;
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);
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;
1848 if((!is_multicast_sta(sta->sta_idx)) && (sta->mac_addr)) {
1849 memset(&sinfo, 0, sizeof(sinfo));
1851 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
1852 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
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);
1864 #ifdef CONFIG_ECRNX_BFMER
1865 if (ecrnx_hw->mod_params->bfmer)
1866 ecrnx_send_bfmer_enable(ecrnx_hw, sta, params->vht_capa);
1868 ecrnx_mu_group_sta_init(sta, params->vht_capa);
1869 #endif /* CONFIG_ECRNX_BFMER */
1871 #define PRINT_STA_FLAG(f) \
1872 (params->sta_flags_set & BIT(NL80211_STA_FLAG_##f) ? "["#f"]" : "")
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",
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));
1885 netdev_info(dev, "Add sta %d (%pM) flags=%s%s%s%s%s%s",
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));
1895 #undef PRINT_STA_FLAG
1896 #if defined(CONFIG_ECRNX_DEBUGFS_CUSTOM)
1897 ecrnx_debugfs_add_station_in_ap_mode(ecrnx_hw, sta, params);
1906 clear_bit(ECRNX_DEV_ADDING_STA, &ecrnx_hw->flags);
1912 * @del_station: Remove a station
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))
1918 #elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))
1921 struct station_del_parameters *params
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;
1930 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
1931 const u8 *mac = NULL;
1936 if(list_empty(&ecrnx_vif->ap.sta_list)) {
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;
1948 spin_unlock_bh(&ecrnx_hw->cb_lock);
1950 if (cur->vif_idx != cur->vlan_idx) {
1951 struct ecrnx_vif *vlan_vif;
1952 vlan_vif = ecrnx_hw->vif_table[cur->vlan_idx];
1954 if ((ECRNX_VIF_TYPE(vlan_vif) == NL80211_IFTYPE_AP_VLAN) &&
1955 (vlan_vif->use_4addr)) {
1956 vlan_vif->ap_vlan.sta_4a = NULL;
1958 WARN(1, "Deleting sta belonging to VLAN other than AP_VLAN 4A");
1963 ecrnx_txq_sta_deinit(ecrnx_hw, cur);
1964 ecrnx_rx_reord_sta_deinit(ecrnx_hw, cur->sta_idx, true);
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);
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) {
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);
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 */
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);
2001 if ((!found) && (mac))
2004 ecrnx_update_mesh_power_mode(ecrnx_vif);
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.
2016 static int ecrnx_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,
2017 const u8 *mac, struct station_parameters *params)
2019 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2020 struct ecrnx_vif *vif = netdev_priv(dev);
2021 struct ecrnx_sta *sta;
2023 sta = ecrnx_get_sta(ecrnx_hw, mac);
2026 /* Add the TDLS station */
2027 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
2029 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
2030 struct me_sta_add_cfm me_sta_add_cfm;
2033 /* Indicate we are in a STA addition process - This will allow handling
2034 * potential PS mode change indications correctly
2036 set_bit(ECRNX_DEV_ADDING_STA, &ecrnx_hw->flags);
2038 /* Forward the information to the LMAC */
2039 if ((error = ecrnx_send_me_sta_add(ecrnx_hw, params, mac, ecrnx_vif->vif_index,
2044 switch (me_sta_add_cfm.status)
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;
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;
2065 sta->uapsd_tids &= ~(1 << tid);
2067 memcpy(sta->mac_addr, mac, ETH_ALEN);
2068 ecrnx_dbgfs_register_sta(ecrnx_hw, sta);
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;
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)
2084 if (!ecrnx_vif->tdls_chsw_prohibited)
2086 sta->tdls.chsw_allowed = true;
2087 ecrnx_vif->sta.tdls_sta = sta;
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);
2094 ecrnx_mu_group_sta_init(sta, NULL);
2095 #endif /* CONFIG_ECRNX_BFMER */
2097 #define PRINT_STA_FLAG(f) \
2098 (params->sta_flags_set & BIT(NL80211_STA_FLAG_##f) ? "["#f"]" : "")
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",
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));
2112 netdev_info(dev, "Add %s TDLS sta %d (%pM) flags=%s%s%s%s%s%s",
2113 sta->tdls.initiator ? "initiator" : "responder",
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));
2122 #undef PRINT_STA_FLAG
2131 clear_bit(ECRNX_DEV_ADDING_STA, &ecrnx_hw->flags);
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,
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);
2150 if (params->local_pm != NL80211_MESH_POWER_UNKNOWN) {
2151 sta->mesh_pm = params->local_pm;
2152 ecrnx_update_mesh_power_mode(vif);
2160 vif = netdev_priv(params->vlan);
2161 vlan_idx = vif->vif_index;
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;
2169 if ((ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_AP_VLAN) &&
2171 WARN((vif->ap_vlan.sta_4a),
2172 "4A AP_VLAN interface with more than one sta");
2173 vif->ap_vlan.sta_4a = sta;
2176 if ((ECRNX_VIF_TYPE(old_vif) == NL80211_IFTYPE_AP_VLAN) &&
2177 (old_vif->use_4addr)) {
2178 old_vif->ap_vlan.sta_4a = NULL;
2187 * @start_ap: Start acting in AP mode defined by the parameters.
2189 static int ecrnx_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
2190 struct cfg80211_ap_settings *settings)
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;
2199 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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)))
2207 switch (apm_start_cfm.status)
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];
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;
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;
2232 ecrnx_txq_vif_init(ecrnx_hw, ecrnx_vif, txq_status);
2233 spin_unlock_bh(&ecrnx_hw->cb_lock);
2235 netif_tx_start_all_queues(dev);
2236 netif_carrier_on(dev);
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
2242 if (txq_status == 0) {
2243 ecrnx_radar_detection_enable_on_cur_channel(ecrnx_hw);
2248 error = -EINPROGRESS;
2250 case CO_OP_IN_PROGRESS:
2259 netdev_info(dev, "Failed to start AP (%d)", error);
2261 netdev_info(dev, "AP started: ch=%d, bcmc_idx=%d",
2262 ecrnx_vif->ch_index, ecrnx_vif->ap.bcmc_index);
2266 ecrnx_ipc_elem_var_deallocs(ecrnx_hw, &elem);
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.
2276 static int ecrnx_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
2277 struct cfg80211_beacon_data *info)
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;
2286 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2289 buf = ecrnx_build_bcn(bcn, info);
2293 // Sync buffer for FW
2294 if ((error = ecrnx_ipc_elem_var_allocs(ecrnx_hw, &elem, bcn->len, DMA_TO_DEVICE,
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);
2302 ecrnx_ipc_elem_var_deallocs(ecrnx_hw, &elem);
2308 * * @stop_ap: Stop being an AP, including stopping beaconing.
2310 static int ecrnx_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
2312 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2313 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
2314 struct ecrnx_sta *sta;
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);
2322 /* delete any remaining STA*/
2323 while (!list_empty(&ecrnx_vif->ap.sta_list)) {
2324 ecrnx_cfg80211_del_station(wiphy, dev, NULL);
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);
2333 netif_tx_stop_all_queues(dev);
2334 netif_carrier_off(dev);
2336 netdev_info(dev, "AP Stopped");
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.
2347 * Also called internaly with chandef set to NULL simply to retrieve the channel
2348 * configured at firmware level.
2350 static int ecrnx_cfg80211_set_monitor_channel(struct wiphy *wiphy,
2351 struct cfg80211_chan_def *chandef)
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);
2358 if (ecrnx_hw->monitor_vif == ECRNX_INVALID_VIF)
2361 ecrnx_vif = ecrnx_hw->vif_table[ecrnx_hw->monitor_vif];
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))
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))
2376 // Always re-set channel context info
2377 ecrnx_chanctx_unlink(ecrnx_vif);
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)
2385 struct cfg80211_chan_def mon_chandef;
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);
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);
2405 * @probe_client: probe an associated client, must return a cookie that it
2406 * later passes to cfg80211_probe_status().
2408 int ecrnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
2409 const u8 *peer, u64 *cookie)
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))
2420 list_for_each_entry(sta, &vif->ap.sta_list, list) {
2421 if (sta->valid && ether_addr_equal(sta->mac_addr, peer))
2428 ecrnx_send_apm_probe_req(ecrnx_hw, vif, sta, &cfm);
2430 if (cfm.status != CO_OK)
2433 *cookie = (u64)cfm.probe_id;
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.
2443 static int ecrnx_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
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.)
2456 static int ecrnx_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
2457 enum nl80211_tx_power_setting type, int mbm)
2459 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2460 struct ecrnx_vif *vif;
2464 if (type == NL80211_TX_POWER_AUTOMATIC) {
2467 pwr = MBM_TO_DBM(mbm);
2471 vif = container_of(wdev, struct ecrnx_vif, wdev);
2472 res = ecrnx_send_set_power(ecrnx_hw, vif->vif_index, pwr, NULL);
2474 list_for_each_entry(vif, &ecrnx_hw->vifs, list) {
2475 res = ecrnx_send_set_power(ecrnx_hw, vif->vif_index, pwr, NULL);
2485 * @set_power_mgmt: set the power save to one of those two modes:
2487 * Power-save on - Dynamic mode
2489 static int ecrnx_cfg80211_set_power_mgmt(struct wiphy *wiphy,
2490 struct net_device *dev,
2491 bool enabled, int timeout)
2493 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2496 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2498 netdev_info(dev, "Ignore timeout value %d", timeout);
2500 if (!(ecrnx_hw->version_cfm.features & BIT(MM_FEAT_PS_BIT)))
2504 /* Switch to Dynamic Power Save */
2505 ps_mode = MM_PS_MODE_ON_DYN;
2507 /* Exit Power Save */
2508 ps_mode = MM_PS_MODE_OFF;
2511 return ecrnx_send_me_set_ps_mode(ecrnx_hw, ps_mode);
2514 static int ecrnx_cfg80211_set_txq_params(struct wiphy *wiphy, struct net_device *dev,
2515 struct ieee80211_txq_params *params)
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;
2522 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2524 hw_queue = ecrnx_ac2hwq[0][params->ac];
2526 aifs = params->aifs;
2527 cwmin = fls(params->cwmin);
2528 cwmax = fls(params->cwmax);
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;
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);
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().
2549 ecrnx_cfg80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
2550 struct ieee80211_channel *chan,
2551 unsigned int duration, u64 *cookie)
2553 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2554 struct ecrnx_vif *ecrnx_vif = netdev_priv(wdev->netdev);
2555 struct ecrnx_roc *roc;
2557 unsigned long timer = 0;
2559 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2561 /* For debug purpose (use ftrace kernel option) */
2562 trace_roc(ecrnx_vif->vif_index, chan->center_freq, duration);
2564 /* Check that no other RoC procedure has been launched */
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);
2574 ECRNX_PRINT("wait_event: wake up!!! timer:%ld \n", timer);
2576 ECRNX_PRINT("wait_event: timout!!!\n");
2581 /* Allocate a temporary RoC element */
2582 roc = kmalloc(sizeof(struct ecrnx_roc), GFP_KERNEL);
2584 /* Verify that element has well been allocated */
2588 /* Initialize the RoC information element */
2589 roc->vif = ecrnx_vif;
2591 roc->duration = duration;
2592 roc->internal = false;
2593 roc->on_chan = false;
2595 /* Initialize the OFFCHAN TX queue to allow off-channel transmissions */
2596 ecrnx_txq_offchan_init(ecrnx_vif);
2598 /* Forward the information to the FMAC */
2599 ecrnx_hw->roc = roc;
2600 error = ecrnx_send_roc(ecrnx_hw, ecrnx_vif, chan, duration);
2602 /* If no error, keep all the information for handling of end of procedure */
2605 /* Set the cookie value */
2606 *cookie = (u64)(ecrnx_hw->roc_cookie);
2608 #ifdef CONFIG_ECRNX_P2P
2609 if(ecrnx_vif->mgmt_reg_stypes & BIT(IEEE80211_STYPE_PROBE_REQ >> 4))
2611 if(ecrnx_send_p2p_start_listen_req(ecrnx_hw, ecrnx_vif, duration))
2612 ECRNX_ERR("P2P: start_listen failed\n");
2617 ecrnx_hw->roc = NULL;
2618 ecrnx_txq_offchan_deinit(ecrnx_vif);
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.
2629 static int ecrnx_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
2630 struct wireless_dev *wdev,
2633 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2634 struct ecrnx_vif *ecrnx_vif = netdev_priv(wdev->netdev);
2637 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2639 /* For debug purpose (use ftrace kernel option) */
2640 trace_cancel_roc(ecrnx_vif->vif_index);
2642 /* Check if a RoC procedure is pending */
2645 #ifdef CONFIG_ECRNX_P2P
2646 //if(ecrnx_vif->mgmt_reg_stypes & BIT(IEEE80211_STYPE_PROBE_REQ >> 4))
2648 error = ecrnx_send_p2p_cancel_listen_req(ecrnx_hw, ecrnx_vif);
2650 ECRNX_PRINT("P2P: cancel_listen OK!!!\n");
2652 ECRNX_ERR("P2P: cancel_listen failed, error=%d\n", error);
2655 /* Forward the information to the FMAC */
2656 return ecrnx_send_cancel_roc(ecrnx_hw);
2660 * @dump_survey: get site survey information.
2662 static int ecrnx_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *netdev,
2663 int idx, struct survey_info *info)
2665 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
2666 struct ieee80211_supported_band *sband;
2667 struct ecrnx_survey_info *ecrnx_survey;
2669 //ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2671 if (idx >= ARRAY_SIZE(ecrnx_hw->survey))
2674 ecrnx_survey = &ecrnx_hw->survey[idx];
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;
2684 #ifdef CONFIG_ECRNX_5G
2685 // Check if provided index matches with a supported 5GHz channel
2686 sband = wiphy->bands[NL80211_BAND_5GHZ];
2688 if (!sband || idx >= sband->n_channels)
2693 info->channel = &sband->channels[idx];
2694 info->filled = ecrnx_survey->filled;
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;
2701 // Set the survey report as not used
2702 ecrnx_survey->filled = 0;
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.
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;
2720 if (!ecrnx_vif->up) {
2724 if (ecrnx_vif->vif_index == ecrnx_hw->monitor_vif)
2726 //retrieve channel from firmware
2727 ecrnx_cfg80211_set_monitor_channel(wiphy, NULL);
2730 //Check if channel context is valid
2731 if(!ecrnx_chanctx_valid(ecrnx_hw, ecrnx_vif->ch_index)){
2735 ctxt = &ecrnx_hw->chanctx_table[ecrnx_vif->ch_index];
2736 *chandef = ctxt->chan_def;
2742 * @mgmt_tx: Transmit a management frame.
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,
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))
2755 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
2756 bool dont_wait_for_ack,
2759 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
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;
2769 struct ieee80211_mgmt *mgmt = (void *)buf;
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;
2777 case NL80211_IFTYPE_AP:
2778 case NL80211_IFTYPE_P2P_GO:
2779 case NL80211_IFTYPE_MESH_POINT:
2782 case NL80211_IFTYPE_STATION:
2783 case NL80211_IFTYPE_P2P_CLIENT:
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);
2792 trace_mgmt_tx((channel) ? channel->center_freq : 0,
2793 ecrnx_vif->vif_index, (ecrnx_sta) ? ecrnx_sta->sta_idx : 0xFF,
2796 if (ap || ecrnx_sta)
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))
2804 if(ieee80211_is_probe_resp(mgmt->frame_control))
2805 goto p2p_send_frame;
2807 /* Otherwise ROC is needed */
2811 /* Check that a RoC is already pending */
2812 if (ecrnx_hw->roc) {
2813 /* Get VIF used for current ROC */
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))
2824 /* Start a ROC procedure for 30ms */
2825 error = ecrnx_cfg80211_remain_on_channel(wiphy, wdev, channel,
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);
2840 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2845 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2846 return ecrnx_start_mgmt_xmit(ecrnx_vif, ecrnx_sta, params, offchan, cookie);
2848 return ecrnx_start_mgmt_xmit(ecrnx_vif, ecrnx_sta, channel, offchan, wait, buf, len, no_cck, dont_wait_for_ack, cookie);
2853 * @start_radar_detection: Start radar detection in the driver.
2855 static int ecrnx_cfg80211_start_radar_detection(struct wiphy *wiphy,
2856 struct net_device *dev,
2857 struct cfg80211_chan_def *chandef,
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;
2864 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
2865 ecrnx_radar_start_cac(&ecrnx_hw->radar, cac_time_ms, ecrnx_vif);
2867 ecrnx_send_apm_start_cac_req(ecrnx_hw, ecrnx_vif, chandef, &cfm);
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,
2876 spin_unlock_bh(&ecrnx_hw->cb_lock);
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.
2889 static int ecrnx_cfg80211_update_ft_ies(struct wiphy *wiphy,
2890 struct net_device *dev,
2891 struct cfg80211_update_ft_ies_params *ftie)
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;
2898 u8 *ft_assoc_ies, *pos;
2899 if ((ECRNX_VIF_TYPE(vif) != NL80211_IFTYPE_STATION) ||
2900 (vif->sta.ft_assoc_ies == NULL))
2902 for_each_ecrnx_element(elem, ftie->ie, ftie->ie_len) {
2903 if (elem->id == WLAN_EID_RSN)
2905 else if (elem->id == WLAN_EID_MOBILITY_DOMAIN)
2907 else if (elem->id == WLAN_EID_FAST_BSS_TRANSITION)
2910 netdev_warn(dev, "Unexpected FT element %d\n", elem->id);
2913 netdev_warn(dev, "Didn't find Mobility_Domain Element\n");
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");
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);
2927 ft_assoc_ies = kmalloc(vif->sta.ft_assoc_ies_len - fties_len + ftie->ie_len,
2929 if (!ft_assoc_ies) {
2930 netdev_warn(dev, "Fail to allocate buffer for association elements");
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");
2939 netdev_warn(dev, "Found several RSN element");
2942 memcpy(pos, rsne, sizeof(*rsne) + rsne->datalen);
2943 pos += sizeof(*rsne) + rsne->datalen;
2946 } else if (elem->id == WLAN_EID_MOBILITY_DOMAIN) {
2948 netdev_warn(dev, "Found several Mobility Domain element");
2951 memcpy(pos, mde, sizeof(*mde) + mde->datalen);
2952 pos += sizeof(*mde) + mde->datalen;
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");
2961 netdev_warn(dev, "found several Fast Transition element");
2964 memcpy(pos, fte, sizeof(*fte) + fte->datalen);
2965 pos += sizeof(*fte) + fte->datalen;
2971 memcpy(pos, fte, sizeof(*fte) + fte->datalen);
2972 pos += sizeof(*fte) + fte->datalen;
2975 memcpy(pos, elem, sizeof(*elem) + elem->datalen);
2976 pos += sizeof(*elem) + elem->datalen;
2980 memcpy(pos, fte, sizeof(*fte) + fte->datalen);
2981 pos += sizeof(*fte) + fte->datalen;
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");
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) {
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");
3015 kfree(ft_assoc_ies);
3020 * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold.
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)
3026 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3027 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3029 return ecrnx_send_cfg_rssi_req(ecrnx_hw, ecrnx_vif->vif_index, rssi_thold, rssi_hyst);
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.
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)
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];
3059 if (params->n_counter_offsets_beacon > BCN_MAX_CSA_CPT)
3062 /* Build the new beacon with CSA IE */
3064 buf = ecrnx_build_bcn(bcn, ¶ms->beacon_csa);
3068 memset(csa_oft, 0, sizeof(csa_oft));
3069 for (i = 0; i < params->n_counter_offsets_beacon; i++)
3071 csa_oft[i] = params->counter_offsets_beacon[i] + bcn->head_len +
3075 /* If count is set to 0 (i.e anytime after this beacon) force it to 2 */
3076 if (params->count == 0) {
3078 for (i = 0; i < params->n_counter_offsets_beacon; i++)
3080 buf[csa_oft[i]] = 2;
3084 if ((error = ecrnx_ipc_elem_var_allocs(ecrnx_hw, &elem, bcn->len,
3085 DMA_TO_DEVICE, buf, NULL, NULL))) {
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);
3098 bcn_after = &csa->bcn;
3099 buf = ecrnx_build_bcn(bcn_after, ¶ms->beacon_after);
3106 if ((error = ecrnx_ipc_elem_var_allocs(ecrnx_hw, &csa->elem, bcn_after->len,
3107 DMA_TO_DEVICE, buf, NULL, NULL))) {
3113 csa->chandef = params->chandef;
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);
3123 INIT_WORK(&csa->work, ecrnx_csa_finish);
3124 cfg80211_ch_switch_started_notify(dev, &csa->chandef, params->count);
3128 ecrnx_ipc_elem_var_deallocs(ecrnx_hw, &elem);
3134 * @tdls_mgmt: prepare TDLS action frame packets and forward them to FW
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)
3141 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3142 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3145 /* make sure we support TDLS */
3146 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
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))
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__);
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__);
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;
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);
3189 ECRNX_ERR("%s: Unknown TDLS mgmt/action frame %pM\n",
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;
3209 * @tdls_oper: execute TDLS operation
3211 static int ecrnx_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
3212 const u8 *peer, enum nl80211_tdls_operation oper)
3214 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3215 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3218 if (oper != NL80211_TDLS_DISABLE_LINK)
3221 if (!ecrnx_vif->sta.tdls_sta) {
3222 ECRNX_ERR("%s: TDLS station %pM does not exist\n", __func__, peer);
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,
3231 ecrnx_vif->sta.tdls_sta->tdls.chsw_en = false;
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))
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 */
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;
3264 * @tdls_channel_switch: enable TDLS channel switch
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)
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;
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);
3282 if (!ecrnx_sta->tdls.chsw_allowed) {
3283 ECRNX_ERR("%s: TDLS station %pM does not support TDLS channel switch\n", __func__, addr);
3287 error = ecrnx_send_tdls_chan_switch_req(ecrnx_hw, ecrnx_vif, ecrnx_sta,
3288 ecrnx_sta->tdls.initiator,
3289 oper_class, chandef, &cfm);
3294 ecrnx_sta->tdls.chsw_en = true;
3297 ECRNX_ERR("%s: TDLS channel switch already enabled and only one is supported\n", __func__);
3303 * @tdls_cancel_channel_switch: disable TDLS channel switch
3305 static void ecrnx_cfg80211_tdls_cancel_channel_switch(struct wiphy *wiphy,
3306 struct net_device *dev,
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;
3317 if (!ecrnx_send_tdls_cancel_chan_switch_req(ecrnx_hw, ecrnx_vif,
3319 ecrnx_sta->tdls.chsw_en = false;
3323 * @change_bss: Modify parameters for a given BSS (mainly for AP mode).
3325 static int ecrnx_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev,
3326 struct bss_parameters *params)
3328 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3329 int res = -EOPNOTSUPP;
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)) {
3335 if (params->ap_isolate)
3336 ecrnx_vif->ap.flags |= ECRNX_AP_ISOLATE;
3338 ecrnx_vif->ap.flags &= ~ECRNX_AP_ISOLATE;
3348 * @get_station: get station information for the station identified by @mac
3350 static int ecrnx_fill_station_info(struct ecrnx_sta *sta, struct ecrnx_vif *vif,
3351 struct station_info *sinfo)
3353 struct ecrnx_sta_stats *stats = &sta->stats;
3354 struct rx_vector_1 *rx_vect1 = &stats->last_rx.rx_vect1;
3357 sinfo->generation = vif->generation;
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;
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;
3372 case PHY_CHNL_BW_40:
3373 sinfo->rxrate.bw = RATE_INFO_BW_40;
3375 case PHY_CHNL_BW_80:
3376 sinfo->rxrate.bw = RATE_INFO_BW_80;
3378 case PHY_CHNL_BW_160:
3379 sinfo->rxrate.bw = RATE_INFO_BW_160;
3382 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
3383 sinfo->rxrate.bw = RATE_INFO_BW_HE_RU;
3385 sinfo->rxrate.bw = RATE_INFO_BW_160;
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;
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;
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;
3411 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
3413 case FORMATMOD_HE_MU:
3414 sinfo->rxrate.he_ru_alloc = rx_vect1->he.ru_size;
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;
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 |
3437 STATION_INFO_RX_PACKETS |
3438 STATION_INFO_TX_PACKETS |
3439 STATION_INFO_SIGNAL |
3440 STATION_INFO_RX_BITRATE);
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));
3452 // Mesh specific info
3453 if (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_MESH_POINT)
3455 struct mesh_peer_info_cfm peer_info_cfm;
3456 if (ecrnx_send_mesh_peer_info_req(vif->ecrnx_hw, vif, sta->sta_idx,
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;
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;
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)|
3483 sinfo->txrate.legacy = 0x6818;
3488 static int ecrnx_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
3489 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))
3494 struct station_info *sinfo)
3496 struct ecrnx_vif *vif = netdev_priv(dev);
3497 struct ecrnx_sta *sta = NULL;
3499 if (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_MONITOR)
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))
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)) {
3518 return ecrnx_fill_station_info(sta, vif, sinfo);
3523 int ecrnx_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
3524 int idx, u8 *mac, struct station_info *sinfo)
3526 struct ecrnx_vif *vif = netdev_priv(dev);
3527 struct ecrnx_sta *sta = NULL;
3529 if (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_MONITOR)
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)
3536 struct ecrnx_sta *sta_iter;
3538 list_for_each_entry(sta_iter, &vif->ap.sta_list, list) {
3551 memcpy(mac, &sta->mac_addr, ETH_ALEN);
3553 return ecrnx_fill_station_info(sta, vif, sinfo);
3557 * @add_mpath: add a fixed mesh path
3559 static int ecrnx_cfg80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
3560 const u8 *dst, const u8 *next_hop)
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;
3566 if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3569 return ecrnx_send_mesh_path_update_req(ecrnx_hw, ecrnx_vif, dst, next_hop, &cfm);
3573 * @del_mpath: delete a given mesh path
3575 static int ecrnx_cfg80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
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;
3582 if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3585 return ecrnx_send_mesh_path_update_req(ecrnx_hw, ecrnx_vif, dst, NULL, &cfm);
3589 * @change_mpath: change a given mesh path
3591 static int ecrnx_cfg80211_change_mpath(struct wiphy *wiphy, struct net_device *dev,
3592 const u8 *dst, const u8 *next_hop)
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;
3598 if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3601 return ecrnx_send_mesh_path_update_req(ecrnx_hw, ecrnx_vif, dst, next_hop, &cfm);
3605 * @get_mpath: get a mesh path for the given parameters
3607 static int ecrnx_cfg80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
3608 u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
3610 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3611 struct ecrnx_mesh_path *mesh_path = NULL;
3612 struct ecrnx_mesh_path *cur;
3614 if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
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)) {
3627 if (mesh_path == NULL)
3630 /* Copy next HOP MAC address */
3631 if (mesh_path->nhop_sta)
3632 memcpy(next_hop, &mesh_path->nhop_sta->mac_addr, ETH_ALEN);
3634 /* Fill path information */
3636 pinfo->generation = ecrnx_vif->generation;
3642 * @dump_mpath: dump mesh path callback -- resume dump at index @idx
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)
3648 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3649 struct ecrnx_mesh_path *mesh_path = NULL;
3650 struct ecrnx_mesh_path *cur;
3653 if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3656 list_for_each_entry(cur, &ecrnx_vif->ap.mpath_list, list) {
3666 if (mesh_path == NULL)
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);
3674 /* Fill path information */
3676 pinfo->generation = ecrnx_vif->generation;
3682 * @get_mpp: get a mesh proxy path for the given parameters
3684 static int ecrnx_cfg80211_get_mpp(struct wiphy *wiphy, struct net_device *dev,
3685 u8 *dst, u8 *mpp, struct mpath_info *pinfo)
3687 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3688 struct ecrnx_mesh_proxy *mesh_proxy = NULL;
3689 struct ecrnx_mesh_proxy *cur;
3691 if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3694 list_for_each_entry(cur, &ecrnx_vif->ap.proxy_list, list) {
3699 /* Compare the path target address and the provided destination address */
3700 if (memcmp(dst, &cur->ext_sta_addr, ETH_ALEN)) {
3708 if (mesh_proxy == NULL)
3711 memcpy(mpp, &mesh_proxy->proxy_addr, ETH_ALEN);
3713 /* Fill path information */
3715 pinfo->generation = ecrnx_vif->generation;
3721 * @dump_mpp: dump mesh proxy path callback -- resume dump at index @idx
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)
3726 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3727 struct ecrnx_mesh_proxy *mesh_proxy = NULL;
3728 struct ecrnx_mesh_proxy *cur;
3731 if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3734 list_for_each_entry(cur, &ecrnx_vif->ap.proxy_list, list) {
3748 if (mesh_proxy == NULL)
3751 /* Copy target MAC address */
3752 memcpy(dst, &mesh_proxy->ext_sta_addr, ETH_ALEN);
3753 memcpy(mpp, &mesh_proxy->proxy_addr, ETH_ALEN);
3755 /* Fill path information */
3757 pinfo->generation = ecrnx_vif->generation;
3763 * @get_mesh_config: Get the current mesh configuration
3765 static int ecrnx_cfg80211_get_mesh_config(struct wiphy *wiphy, struct net_device *dev,
3766 struct mesh_config *conf)
3768 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3770 if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3777 * @update_mesh_config: Update mesh parameters on a running mesh.
3779 static int ecrnx_cfg80211_update_mesh_config(struct wiphy *wiphy, struct net_device *dev,
3780 u32 mask, const struct mesh_config *nconf)
3782 struct ecrnx_vif *ecrnx_vif = netdev_priv(dev);
3783 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
3784 struct mesh_update_cfm cfm;
3787 if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
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;
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);
3806 status = ecrnx_send_mesh_update_req(ecrnx_hw, ecrnx_vif, mask, nconf, &cfm);
3808 if (!status && (cfm.status != 0))
3815 * @join_mesh: join the mesh network with the specified parameters
3816 * (invoked with the wireless_dev mutex held)
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)
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;
3826 /* STA for BC/MC traffic */
3827 struct ecrnx_sta *sta;
3829 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
3831 if (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)
3834 /* Forward the information to the UMAC */
3835 if ((error = ecrnx_send_mesh_start_req(ecrnx_hw, ecrnx_vif, conf, setup, &mesh_start_cfm))) {
3839 /* Check the status */
3840 switch (mesh_start_cfm.status) {
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;
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;
3853 sta = &ecrnx_hw->sta_table[mesh_start_cfm.bcmc_idx];
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;
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;
3870 ecrnx_txq_vif_init(ecrnx_hw, ecrnx_vif, txq_status);
3871 spin_unlock_bh(&ecrnx_hw->cb_lock);
3873 netif_tx_start_all_queues(dev);
3874 netif_carrier_on(dev);
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
3880 if (ecrnx_hw->cur_chanctx == mesh_start_cfm.ch_idx) {
3881 ecrnx_radar_detection_enable_on_cur_channel(ecrnx_hw);
3886 error = -EINPROGRESS;
3894 /* Print information about the operation */
3896 netdev_info(dev, "Failed to start MP (%d)", error);
3898 netdev_info(dev, "MP started: ch=%d, bcmc_idx=%d",
3899 ecrnx_vif->ch_index, ecrnx_vif->ap.bcmc_index);
3906 * @leave_mesh: leave the current mesh network
3907 * (invoked with the wireless_dev mutex held)
3909 static int ecrnx_cfg80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
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;
3916 error = ecrnx_send_mesh_stop_req(ecrnx_hw, ecrnx_vif, &mesh_stop_cfm);
3919 /* Check the status */
3920 switch (mesh_stop_cfm.status) {
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);
3930 netif_tx_stop_all_queues(dev);
3931 netif_carrier_off(dev);
3942 netdev_info(dev, "Failed to stop MP");
3944 netdev_info(dev, "MP Stopped");
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)
3956 struct ecrnx_vif *ecrnx_vif = netdev_priv(wdev->netdev);
3958 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
3960 if (ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_STATION)
3962 ecrnx_vif->mgmt_reg_stypes = upd->interface_stypes & BIT(IEEE80211_STYPE_PROBE_REQ >> 4);
3966 static void ecrnx_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
3967 struct wireless_dev *wdev,
3968 u16 frame_type, bool reg)
3970 struct ecrnx_vif *ecrnx_vif = netdev_priv(wdev->netdev);
3974 mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
3977 ecrnx_vif->mgmt_reg_stypes |= BIT(mgmt_type);
3979 ecrnx_vif->mgmt_reg_stypes &= ~BIT(mgmt_type);
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,
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,
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,
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,
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,
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,
4044 .mgmt_frame_register = ecrnx_cfg80211_mgmt_frame_register,
4051 /*********************************************************************
4052 * Init/Exit functions
4053 *********************************************************************/
4054 static void ecrnx_wdev_unregister(struct ecrnx_hw *ecrnx_hw)
4056 struct ecrnx_vif *ecrnx_vif, *tmp;
4059 list_for_each_entry_safe(ecrnx_vif, tmp, &ecrnx_hw->vifs, list) {
4060 ecrnx_cfg80211_del_iface(ecrnx_hw->wiphy, &ecrnx_vif->wdev);
4065 static void ecrnx_set_vers(struct ecrnx_hw *ecrnx_hw)
4067 u32 vers = ecrnx_hw->version_cfm.version_lmac;
4069 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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);
4078 static void ecrnx_reg_notifier(struct wiphy *wiphy,
4079 struct regulatory_request *request)
4081 struct ecrnx_hw *ecrnx_hw = wiphy_priv(wiphy);
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);
4088 static void ecrnx_enable_mesh(struct ecrnx_hw *ecrnx_hw)
4090 struct wiphy *wiphy = ecrnx_hw->wiphy;
4092 if (!ecrnx_mod_params.mesh)
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;
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;
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;
4113 wiphy->interface_modes |= BIT(NL80211_IFTYPE_MESH_POINT);
4115 ecrnx_limits[0].types |= BIT(NL80211_IFTYPE_MESH_POINT);
4116 ecrnx_limits_dfs[0].types |= BIT(NL80211_IFTYPE_MESH_POINT);
4119 int ecrnx_get_cal_result(struct ecrnx_hw *ecrnx_hw)
4122 wifi_cal_data_t *result = &cal_result;
4124 ret = ecrnx_send_cal_result_get_req(ecrnx_hw, result);
4129 void ecrnx_he_init(void)
4131 ecrnx_he_cap.has_he = true;
4132 memset(&ecrnx_he_cap.he_cap_elem, 0, sizeof(struct ieee80211_he_cap_elem));
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);
4146 bool register_drv_done = false;
4147 int ecrnx_cfg80211_init(void *ecrnx_plat, void **platform_data)
4149 struct ecrnx_hw *ecrnx_hw;
4151 struct wiphy *wiphy;
4152 struct wireless_dev *wdev;
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));
4160 dev_err(ecrnx_platform_get_dev(ecrnx_plat), "Failed to create new wiphy\n");
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;
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");
4183 if ((ret = ecrnx_parse_configfile(ecrnx_hw, ECRNX_CONFIG_FW_NAME))) {
4184 wiphy_err(wiphy, "ecrnx_parse_configfile failed\n");
4188 ecrnx_hw->vif_started = 0;
4189 ecrnx_hw->monitor_vif = ECRNX_INVALID_VIF;
4191 ecrnx_hw->scan_ie.addr = NULL;
4193 for (i = 0; i < NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX; i++)
4194 ecrnx_hw->avail_idx_map |= BIT(i);
4196 ecrnx_hwq_init(ecrnx_hw);
4197 ecrnx_txq_prepare(ecrnx_hw);
4199 ecrnx_mu_group_init(ecrnx_hw);
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;
4206 wiphy->mgmt_stypes = ecrnx_default_mgmt_stypes;
4208 wiphy->bands[NL80211_BAND_2GHZ] = &ecrnx_band_2GHz;
4209 #ifdef CONFIG_ECRNX_5G
4210 wiphy->bands[NL80211_BAND_5GHZ] = &ecrnx_band_5GHz;
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 |
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;
4229 wiphy->max_remain_on_channel_duration = ecrnx_hw->mod_params->roc_dur_max;
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 |
4235 wiphy->features |= NL80211_FEATURE_SK_TX_STATUS |
4237 NL80211_FEATURE_VIF_TXPOWER |
4238 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
4239 NL80211_FEATURE_ACTIVE_MONITOR |
4241 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
4242 NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
4246 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
4247 wiphy->features |= NL80211_FEATURE_SAE;
4250 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0)
4254 if (ecrnx_mod_params.tdls)
4256 wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
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;
4264 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
4266 wiphy->cipher_suites = cipher_suites;
4267 wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites) - NB_RESERVED_CIPHER;
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);
4279 #ifndef CONFIG_ECRNX_ESWIN
4280 tasklet_init(&ecrnx_hw->task, ecrnx_task, (unsigned long)ecrnx_hw);
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);
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);
4296 if ((ret = ecrnx_platform_on(ecrnx_hw, NULL)))
4299 if ((ret = ecrnx_get_cal_result(ecrnx_hw))) {
4300 wiphy_err(wiphy, "get cal result failed\n");
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);
4309 memcpy(wiphy->perm_addr, ecrnx_hw->conf_param.mac_addr, ETH_ALEN);
4312 if ((ret = ecrnx_send_reset(ecrnx_hw)))
4314 if ((ret = ecrnx_send_version_req(ecrnx_hw, &ecrnx_hw->version_cfm)))
4316 ecrnx_set_vers(ecrnx_hw);
4318 if ((ret = ecrnx_handle_dynparams(ecrnx_hw, ecrnx_hw->wiphy)))
4321 ecrnx_enable_mesh(ecrnx_hw);
4322 ecrnx_radar_detection_init(&ecrnx_hw->radar);
4324 #ifdef CONFIG_ECRNX_P2P
4325 ecrnx_p2p_listen_init(&ecrnx_hw->p2p_listen);
4328 /* Set parameters to firmware */
4329 ecrnx_send_me_config_req(ecrnx_hw);
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);
4337 if ((ret = wiphy_register(wiphy))) {
4338 wiphy_err(wiphy, "Could not register wiphy device\n");
4339 goto err_register_wiphy;
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);
4350 /* config gain delta */
4351 ecrnx_send_set_gain_delta_req(ecrnx_hw);
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");
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,
4367 #if defined(CONFIG_ECRNX_P2P)
4368 wdev = ecrnx_interface_add(ecrnx_hw, "p2p%d", NET_NAME_UNKNOWN, NL80211_IFTYPE_STATION,
4374 wiphy_err(wiphy, "Failed to instantiate a network device\n");
4376 goto err_add_interface;
4379 wiphy_info(wiphy, "New interface create %s", wdev->netdev->name);
4381 #if defined(CONFIG_ECRNX_DEBUGFS_CUSTOM)
4382 ecrnx_debugfs_init(ecrnx_hw);
4384 register_drv_done = true;
4388 #ifdef CONFIG_ECRNX_DEBUGFS
4391 wiphy_unregister(ecrnx_hw->wiphy);
4394 ecrnx_fw_trace_dump(ecrnx_hw);
4395 ecrnx_platform_off(ecrnx_hw, NULL);
4398 kmem_cache_destroy(ecrnx_hw->sw_txhdr_cache);
4402 ECRNX_DBG(" %s cfg80211 init failed %d!!", __func__, ret);
4409 void ecrnx_cfg80211_deinit(struct ecrnx_hw *ecrnx_hw)
4411 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
4412 if(!register_drv_done)
4417 ecrnx_dbgfs_unregister(ecrnx_hw);
4419 register_drv_done = false;
4421 del_timer_sync(&ecrnx_hw->txq_cleanup);
4422 ecrnx_wdev_unregister(ecrnx_hw);
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;
4430 ecrnx_radar_detection_deinit(&ecrnx_hw->radar);
4431 ecrnx_platform_off(ecrnx_hw, NULL);
4432 kmem_cache_destroy(ecrnx_hw->sw_txhdr_cache);
4438 static int __init ecrnx_mod_init(void)
4440 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
4441 ecrnx_print_version();
4442 return ecrnx_platform_register_drv();
4448 static void __exit ecrnx_mod_exit(void)
4450 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
4452 #if defined(CONFIG_ECRNX_DEBUGFS_CUSTOM)
4453 ecrnx_debugfs_exit();
4456 ecrnx_platform_unregister_drv();
4459 module_init(ecrnx_mod_init);
4460 module_exit(ecrnx_mod_exit);
4462 MODULE_FIRMWARE(ECRNX_CONFIG_FW_NAME);
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");