ARM: Updated WiFi WILC1000 source code:
authorJosep Orga <jorga@somdevices.com>
Sun, 22 Mar 2020 17:58:33 +0000 (18:58 +0100)
committerJosep Orga <jorga@somdevices.com>
Sun, 22 Mar 2020 17:58:33 +0000 (18:58 +0100)
· Based on tag wilc_linux_15_3_1 in https://github.com/linux4wilc/driver/tree/wilc_linux_15_3_1
· Firmware wilc1000_wifi_firmware.bin is located in https://github.com/linux4wilc/firmware/tree/wilc_linux_15_3_1

Signed-off-by: Josep Orga <jorga@somdevices.com>
24 files changed:
drivers/net/wireless/mchp/Makefile
drivers/net/wireless/mchp/host_interface.c [deleted file]
drivers/net/wireless/mchp/host_interface.h [deleted file]
drivers/net/wireless/mchp/microchip,wilc,sdio.txt [deleted file]
drivers/net/wireless/mchp/microchip,wilc,spi.txt [deleted file]
drivers/net/wireless/mchp/microchip,wilc1000,sdio.txt [new file with mode: 0644]
drivers/net/wireless/mchp/microchip,wilc1000,spi.txt [new file with mode: 0644]
drivers/net/wireless/mchp/sysfs.c
drivers/net/wireless/mchp/wilc_bt.c
drivers/net/wireless/mchp/wilc_hif.c [new file with mode: 0644]
drivers/net/wireless/mchp/wilc_hif.h [new file with mode: 0644]
drivers/net/wireless/mchp/wilc_mon.c
drivers/net/wireless/mchp/wilc_netdev.c
drivers/net/wireless/mchp/wilc_netdev.h
drivers/net/wireless/mchp/wilc_sdio.c
drivers/net/wireless/mchp/wilc_spi.c
drivers/net/wireless/mchp/wilc_wfi_cfgoperations.c
drivers/net/wireless/mchp/wilc_wfi_cfgoperations.h
drivers/net/wireless/mchp/wilc_wfi_netdevice.h
drivers/net/wireless/mchp/wilc_wlan.c
drivers/net/wireless/mchp/wilc_wlan.h
drivers/net/wireless/mchp/wilc_wlan_cfg.c
drivers/net/wireless/mchp/wilc_wlan_cfg.h
drivers/net/wireless/mchp/wilc_wlan_if.h

index 9f440b5..7eb8cf0 100644 (file)
@@ -1,9 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0
 ccflags-y += -I$(src)/ -DWILC_ASIC_A0 -DWILC_DEBUGFS
-ccflags-y += -DDISABLE_PWRSAVE_AND_SCAN_DURING_IP
 
 wilc-objs := wilc_wfi_cfgoperations.o wilc_netdev.o wilc_mon.o \
-                       host_interface.o wilc_wlan_cfg.o wilc_debugfs.o \
+                       wilc_hif.o wilc_wlan_cfg.o wilc_debugfs.o \
                        wilc_wlan.o sysfs.o wilc_bt.o
 
 obj-$(CONFIG_WILC_SDIO) += wilc-sdio.o
diff --git a/drivers/net/wireless/mchp/host_interface.c b/drivers/net/wireless/mchp/host_interface.c
deleted file mode 100644 (file)
index c8eba4f..0000000
+++ /dev/null
@@ -1,2769 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
- * All rights reserved.
- */
-
-#include <linux/etherdevice.h>
-
-#include "wilc_wfi_netdevice.h"
-#include "wilc_netdev.h"
-#include "wilc_wfi_cfgoperations.h"
-
-#define WILC_HIF_SCAN_TIMEOUT_MS                    5000
-#define WILC_HIF_CONNECT_TIMEOUT_MS                 9500
-
-#define WILC_FALSE_FRMWR_CHANNEL                   100
-#define WILC_MAX_RATES_SUPPORTED                   12
-
-/* Generic success will return 0 */
-#define WILC_SUCCESS           0       /* Generic success */
-
-/* Negative numbers to indicate failures */
-/* Generic Fail */
-#define        WILC_FAIL               -100
-/* Busy with another operation*/
-#define        WILC_BUSY               -101
-/* A given argument is invalid*/
-#define        WILC_INVALID_ARGUMENT   -102
-/* An API request would violate the Driver state machine
- * (i.e. to start PID while not camped)
- */
-#define        WILC_INVALID_STATE      -103
-/* In copy operations if the copied data is larger than the allocated buffer*/
-#define        WILC_BUFFER_OVERFLOW    -104
-/* null pointer is passed or used */
-#define WILC_NULL_PTR          -105
-#define        WILC_EMPTY              -107
-#define WILC_FULL              -108
-#define        WILC_TIMEOUT            -109
-/* The required operation have been canceled by the user*/
-#define WILC_CANCELED          -110
-/* The Loaded file is corruped or having an invalid format */
-#define WILC_INVALID_FILE      -112
-/* Cant find the file to load */
-#define WILC_NOT_FOUND         -113
-#define WILC_NO_MEM            -114
-#define WILC_UNSUPPORTED_VERSION -115
-#define WILC_FILE_EOF          -116
-
-#if KERNEL_VERSION(3, 17, 0) > LINUX_VERSION_CODE
-struct ieee80211_wmm_ac_param {
-       u8 aci_aifsn; /* AIFSN, ACM, ACI */
-       u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */
-       __le16 txop_limit;
-} __packed;
-
-struct ieee80211_wmm_param_ie {
-       u8 element_id; /* Element ID: 221 (0xdd); */
-       u8 len; /* Length: 24 */
-       u8 oui[3]; /* 00:50:f2 */
-       u8 oui_type; /* 2 */
-       u8 oui_subtype; /* 1 */
-       u8 version; /* 1 for WMM version 1.0 */
-       u8 qos_info; /* AP/STA specific QoS info */
-       u8 reserved; /* 0 */
-       /* AC_BE, AC_BK, AC_VI, AC_VO */
-       struct ieee80211_wmm_ac_param ac[4];
-} __packed;
-#endif
-
-struct send_buffered_eap {
-       void (*deliver_to_stack)(struct wilc_vif *vif, u8 *buff, u32 size,
-                             u32 pkt_offset, u8 status);
-       void (*eap_buf_param)(void *priv);
-       u8 *buff;
-       unsigned int size;
-       unsigned int pkt_offset;
-       void *user_arg;
-};
-
-struct wilc_rcvd_mac_info {
-       u8 status;
-};
-
-struct wilc_set_multicast {
-       u32 enabled;
-       u32 cnt;
-       u8 *mc_list;
-};
-
-struct host_if_wowlan_trigger {
-       u8 wowlan_trigger;
-};
-
-struct bt_coex_mode {
-       u8 bt_coex;
-};
-
-struct host_if_set_ant {
-       u8 mode;
-       u8 antenna1;
-       u8 antenna2;
-       u8 gpio_mode;
-};
-
-struct wilc_del_all_sta {
-       u8 assoc_sta;
-       u8 mac[WILC_MAX_NUM_STA][ETH_ALEN];
-};
-
-struct wilc_op_mode {
-       __le32 mode;
-};
-
-struct wilc_reg_frame {
-       bool reg;
-       u8 reg_id;
-       __le16 frame_type;
-} __packed;
-
-struct wilc_drv_handler {
-       __le32 handler;
-       u8 mode;
-} __packed;
-
-struct wilc_wep_key {
-       u8 index;
-       u8 key_len;
-       u8 key[0];
-} __packed;
-
-struct wilc_sta_wpa_ptk {
-       u8 mac_addr[ETH_ALEN];
-       u8 key_len;
-       u8 key[0];
-} __packed;
-
-struct wilc_ap_wpa_ptk {
-       u8 mac_addr[ETH_ALEN];
-       u8 index;
-       u8 key_len;
-       u8 key[0];
-} __packed;
-
-struct wilc_gtk_key {
-       u8 mac_addr[ETH_ALEN];
-       u8 rsc[8];
-       u8 index;
-       u8 key_len;
-       u8 key[0];
-} __packed;
-
-union wilc_message_body {
-       struct wilc_rcvd_net_info net_info;
-       struct wilc_rcvd_mac_info mac_info;
-       struct wilc_set_multicast mc_info;
-       struct wilc_remain_ch remain_on_ch;
-       char *data;
-       struct send_buffered_eap send_buff_eap;
-       struct host_if_set_ant set_ant;
-       struct host_if_wowlan_trigger wow_trigger;
-       struct bt_coex_mode bt_coex_mode;
-};
-
-struct host_if_msg {
-       union wilc_message_body body;
-       struct wilc_vif *vif;
-       struct work_struct work;
-       void (*fn)(struct work_struct *ws);
-       struct completion work_comp;
-       bool is_sync;
-};
-
-struct wilc_noa_opp_enable {
-       u8 ct_window;
-       u8 cnt;
-       __le32 duration;
-       __le32 interval;
-       __le32 start_time;
-} __packed;
-
-struct wilc_noa_opp_disable {
-       u8 cnt;
-       __le32 duration;
-       __le32 interval;
-       __le32 start_time;
-} __packed;
-
-struct wilc_join_bss_param {
-       char ssid[IEEE80211_MAX_SSID_LEN];
-       u8 ssid_terminator;
-       u8 bss_type;
-       u8 ch;
-       __le16 cap_info;
-       u8 sa[ETH_ALEN];
-       u8 bssid[ETH_ALEN];
-       __le16 beacon_period;
-       u8 dtim_period;
-       u8 supp_rates[WILC_MAX_RATES_SUPPORTED + 1];
-       u8 wmm_cap;
-       u8 uapsd_cap;
-       u8 ht_capable;
-       u8 rsn_found;
-       u8 rsn_grp_policy;
-       u8 mode_802_11i;
-       u8 p_suites[3];
-       u8 akm_suites[3];
-       u8 rsn_cap[2];
-       u8 noa_enabled;
-       __le32 tsf_lo;
-       u8 idx;
-       u8 opp_enabled;
-       union {
-               struct wilc_noa_opp_disable opp_dis;
-               struct wilc_noa_opp_enable opp_en;
-       };
-} __packed;
-
-/* 'msg' should be free by the caller for syc */
-static struct host_if_msg*
-wilc_alloc_work(struct wilc_vif *vif, void (*work_fun)(struct work_struct *),
-               bool is_sync)
-{
-       struct host_if_msg *msg;
-
-       if (!work_fun)
-               return ERR_PTR(-EINVAL);
-
-       msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
-       if (!msg)
-               return ERR_PTR(-ENOMEM);
-       msg->fn = work_fun;
-       msg->vif = vif;
-       msg->is_sync = is_sync;
-       if (is_sync)
-               init_completion(&msg->work_comp);
-
-       return msg;
-}
-
-static int wilc_enqueue_work(struct host_if_msg *msg)
-{
-       INIT_WORK(&msg->work, msg->fn);
-
-       if (!msg->vif || !msg->vif->wilc || !msg->vif->wilc->hif_workqueue)
-               return -EINVAL;
-
-       if (!queue_work(msg->vif->wilc->hif_workqueue, &msg->work))
-               return -EINVAL;
-
-       return 0;
-}
-
-/* The idx starts from 0 to (NUM_CONCURRENT_IFC - 1), but 0 index used as
- * special purpose in wilc device, so we add 1 to the index to starts from 1.
- * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC.
- */
-int wilc_get_vif_idx(struct wilc_vif *vif)
-{
-       return vif->idx + 1;
-}
-
-/* We need to minus 1 from idx which is from wilc device to get real index
- * of wilc->vif[], because we add 1 when pass to wilc device in the function
- * wilc_get_vif_idx.
- * As a result, the index should be between 0 and (NUM_CONCURRENT_IFC - 1).
- */
-static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx)
-{
-       int index = idx - 1;
-
-       if (index < 0 || index >= WILC_NUM_CONCURRENT_IFC)
-               return NULL;
-
-       return wilc->vif[index];
-}
-
-static void handle_send_buffered_eap(struct work_struct *work)
-{
-       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-       struct wilc_vif *vif = msg->vif;
-       struct send_buffered_eap *hif_buff_eap = &msg->body.send_buff_eap;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Sending bufferd eapol to WPAS\n");
-       if (!hif_buff_eap->buff)
-               goto out;
-
-       if (hif_buff_eap->deliver_to_stack)
-               hif_buff_eap->deliver_to_stack(vif, hif_buff_eap->buff,
-                                              hif_buff_eap->size,
-                                              hif_buff_eap->pkt_offset,
-                                              PKT_STATUS_BUFFERED);
-       if (hif_buff_eap->eap_buf_param)
-               hif_buff_eap->eap_buf_param(hif_buff_eap->user_arg);
-
-       if (hif_buff_eap->buff != NULL) {
-               kfree(hif_buff_eap->buff);
-               hif_buff_eap->buff = NULL;
-       }
-
-out:
-       kfree(msg);
-}
-
-int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
-             u8 *ch_freq_list, u8 ch_list_len,
-             void (*scan_result_fn)(enum scan_event,
-                                    struct wilc_rcvd_net_info *, void *),
-             void *user_arg, struct cfg80211_scan_request *request)
-{
-       int result = 0;
-       struct wid wid_list[5];
-       u32 index = 0;
-       u32 i, scan_timeout;
-       u8 *buffer;
-       u8 valuesize = 0;
-       u8 *search_ssid_vals = NULL;
-       struct host_if_drv *hif_drv = vif->hif_drv;
-       struct host_if_drv *hif_drv_p2p = get_drv_hndl_by_ifc(vif->wilc,
-                                                             WILC_P2P_IFC);
-       struct host_if_drv *hif_drv_wlan = get_drv_hndl_by_ifc(vif->wilc,
-                                                              WILC_WLAN_IFC);
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Setting SCAN params\n");
-       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Scanning: In [%d] state\n",
-                  hif_drv->hif_state);
-
-       if (hif_drv_p2p != NULL) {
-               if (hif_drv_p2p->hif_state != HOST_IF_IDLE &&
-                   hif_drv_p2p->hif_state != HOST_IF_CONNECTED) {
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "Don't scan. P2P_IFC is in state [%d]\n",
-                                  hif_drv_p2p->hif_state);
-                       result = -EBUSY;
-                       goto error;
-               }
-       }
-
-       if (hif_drv_wlan != NULL) {
-               if (hif_drv_wlan->hif_state != HOST_IF_IDLE &&
-                   hif_drv_wlan->hif_state != HOST_IF_CONNECTED) {
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "Don't scan. WLAN_IFC is in state [%d]\n",
-                                  hif_drv_wlan->hif_state);
-                       result = -EBUSY;
-                       goto error;
-               }
-       }
-       if (vif->connecting) {
-               PRINT_INFO(vif->ndev, GENERIC_DBG,
-                          "Don't do scan in (CONNECTING) state\n");
-               result = -EBUSY;
-               goto error;
-       }
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-       if (vif->obtaining_ip) {
-               PRINT_ER(vif->ndev, "Don't do obss scan\n");
-               result = -EBUSY;
-               goto error;
-       }
-#endif
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Setting SCAN params\n");
-       hif_drv->usr_scan_req.ch_cnt = 0;
-
-       if (request->n_ssids) {
-               for (i = 0; i < request->n_ssids; i++)
-                       valuesize += ((request->ssids[i].ssid_len) + 1);
-               search_ssid_vals = kmalloc(valuesize + 1, GFP_KERNEL);
-               if (search_ssid_vals) {
-                       wid_list[index].id = WID_SSID_PROBE_REQ;
-                       wid_list[index].type = WID_STR;
-                       wid_list[index].val = search_ssid_vals;
-                       buffer = wid_list[index].val;
-
-                       *buffer++ = request->n_ssids;
-
-               PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                          "In Handle_ProbeRequest number of ssid %d\n",
-                        request->n_ssids);
-                       for (i = 0; i < request->n_ssids; i++) {
-                               *buffer++ = request->ssids[i].ssid_len;
-                               memcpy(buffer, request->ssids[i].ssid,
-                                      request->ssids[i].ssid_len);
-                               buffer += request->ssids[i].ssid_len;
-                       }
-                       wid_list[index].size = (s32)(valuesize + 1);
-                       index++;
-               }
-       }
-
-       wid_list[index].id = WID_INFO_ELEMENT_PROBE;
-       wid_list[index].type = WID_BIN_DATA;
-       wid_list[index].val = (s8 *)request->ie;
-       wid_list[index].size = request->ie_len;
-       index++;
-
-       wid_list[index].id = WID_SCAN_TYPE;
-       wid_list[index].type = WID_CHAR;
-       wid_list[index].size = sizeof(char);
-       wid_list[index].val = (s8 *)&scan_type;
-       index++;
-
-#if KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE
-       scan_timeout = WILC_HIF_SCAN_TIMEOUT_MS;
-#else
-       if (scan_type == WILC_FW_PASSIVE_SCAN && request->duration) {
-               wid_list[index].id = WID_PASSIVE_SCAN_TIME;
-               wid_list[index].type = WID_SHORT;
-               wid_list[index].size = sizeof(u16);
-               wid_list[index].val = (s8 *)&request->duration;
-               index++;
-
-               scan_timeout = (request->duration * ch_list_len) + 500;
-       } else {
-               scan_timeout = WILC_HIF_SCAN_TIMEOUT_MS;
-       }
-#endif
-       wid_list[index].id = WID_SCAN_CHANNEL_LIST;
-       wid_list[index].type = WID_BIN_DATA;
-
-       if (ch_freq_list && ch_list_len > 0) {
-               for (i = 0; i < ch_list_len; i++) {
-                       if (ch_freq_list[i] > 0)
-                               ch_freq_list[i] -= 1;
-               }
-       }
-
-       wid_list[index].val = ch_freq_list;
-       wid_list[index].size = ch_list_len;
-       index++;
-
-       wid_list[index].id = WID_START_SCAN_REQ;
-       wid_list[index].type = WID_CHAR;
-       wid_list[index].size = sizeof(char);
-       wid_list[index].val = (s8 *)&scan_source;
-       index++;
-
-       hif_drv->usr_scan_req.scan_result = scan_result_fn;
-       hif_drv->usr_scan_req.arg = user_arg;
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
-                                     index,
-                                     wilc_get_vif_idx(vif));
-       if (result) {
-               PRINT_ER(vif->ndev, "Failed to send scan parameters\n");
-               goto error;
-       } else {
-               hif_drv->scan_timer_vif = vif;
-               PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                          ">> Starting the SCAN timer\n");
-#if KERNEL_VERSION(4, 15, 0) > LINUX_VERSION_CODE
-               hif_drv->scan_timer.data = (unsigned long)hif_drv;
-#endif
-               mod_timer(&hif_drv->scan_timer,
-                         jiffies + msecs_to_jiffies(scan_timeout));
-       }
-
-error:
-
-       kfree(search_ssid_vals);
-
-       return result;
-}
-
-s32 handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
-{
-       s32 result = 0;
-       u8 abort_running_scan;
-       struct wid wid;
-       struct host_if_drv *hif_drv = vif->hif_drv;
-       struct wilc_user_scan_req *scan_req;
-       u8 null_bssid[6] = {0};
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG, "handling scan done\n");
-
-       if (!hif_drv) {
-               PRINT_ER(vif->ndev, "hif driver is NULL\n");
-               return result;
-       }
-
-       if (evt == SCAN_EVENT_DONE) {
-               if (memcmp(hif_drv->assoc_bssid, null_bssid, ETH_ALEN) == 0)
-                       hif_drv->hif_state = HOST_IF_IDLE;
-               else
-                       hif_drv->hif_state = HOST_IF_CONNECTED;
-       } else if (evt == SCAN_EVENT_ABORTED) {
-               PRINT_INFO(vif->ndev, GENERIC_DBG, "Abort running scan\n");
-               abort_running_scan = 1;
-               wid.id = WID_ABORT_RUNNING_SCAN;
-               wid.type = WID_CHAR;
-               wid.val = (s8 *)&abort_running_scan;
-               wid.size = sizeof(char);
-
-               result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                             wilc_get_vif_idx(vif));
-
-               if (result) {
-                       PRINT_ER(vif->ndev, "Failed to set abort running\n");
-                       result = -EFAULT;
-               }
-       }
-
-       scan_req = &hif_drv->usr_scan_req;
-       if (scan_req->scan_result) {
-               scan_req->scan_result(evt, NULL, scan_req->arg);
-               scan_req->scan_result = NULL;
-       }
-
-       return result;
-}
-
-static int wilc_send_connect_wid(struct wilc_vif *vif)
-{
-       int result = 0;
-       struct wid wid_list[4];
-       u32 wid_cnt = 0;
-       struct host_if_drv *hif_drv = vif->hif_drv;
-       struct wilc_conn_info *conn_attr = &hif_drv->conn_info;
-       struct wilc_join_bss_param *bss_param = hif_drv->conn_info.param;
-       struct host_if_drv *hif_drv_p2p = get_drv_hndl_by_ifc(vif->wilc,
-                                                             WILC_P2P_IFC);
-       struct host_if_drv *hif_drv_wlan = get_drv_hndl_by_ifc(vif->wilc,
-                                                              WILC_WLAN_IFC);
-
-       if (hif_drv_p2p != NULL) {
-               if (hif_drv_p2p->hif_state == HOST_IF_SCANNING) {
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "Don't scan. P2P_IFC is in state [%d]\n",
-                        hif_drv_p2p->hif_state);
-                        result = -EFAULT;
-                       goto error;
-               }
-       }
-       if (hif_drv_wlan != NULL) {
-               if (hif_drv_wlan->hif_state == HOST_IF_SCANNING) {
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "Don't scan. WLAN_IFC is in state [%d]\n",
-                        hif_drv_wlan->hif_state);
-                       result = -EFAULT;
-                       goto error;
-               }
-       }
-
-       wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE;
-       wid_list[wid_cnt].type = WID_BIN_DATA;
-       wid_list[wid_cnt].val = conn_attr->req_ies;
-       wid_list[wid_cnt].size = conn_attr->req_ies_len;
-       wid_cnt++;
-
-       wid_list[wid_cnt].id = WID_11I_MODE;
-       wid_list[wid_cnt].type = WID_CHAR;
-       wid_list[wid_cnt].size = sizeof(char);
-       wid_list[wid_cnt].val = (s8 *)&conn_attr->security;
-       wid_cnt++;
-
-       PRINT_D(vif->ndev, HOSTINF_DBG, "Encrypt Mode = %x\n",
-               conn_attr->security);
-       wid_list[wid_cnt].id = WID_AUTH_TYPE;
-       wid_list[wid_cnt].type = WID_CHAR;
-       wid_list[wid_cnt].size = sizeof(char);
-       wid_list[wid_cnt].val = (s8 *)&conn_attr->auth_type;
-       wid_cnt++;
-
-       PRINT_D(vif->ndev, HOSTINF_DBG, "Authentication Type = %x\n",
-               conn_attr->auth_type);
-       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                  "Connecting to network on channel %d\n", conn_attr->ch);
-
-       wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED;
-       wid_list[wid_cnt].type = WID_STR;
-       wid_list[wid_cnt].size = sizeof(*bss_param);
-       wid_list[wid_cnt].val = (u8 *)bss_param;
-       wid_cnt++;
-
-       PRINT_INFO(vif->ndev, GENERIC_DBG, "send HOST_IF_WAITING_CONN_RESP\n");
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
-                                     wid_cnt,
-                                     wilc_get_vif_idx(vif));
-       if (result) {
-               PRINT_ER(vif->ndev, "failed to send config packet\n");
-               goto error;
-       } else {
-               PRINT_INFO(vif->ndev, GENERIC_DBG,
-                          "set HOST_IF_WAITING_CONN_RESP\n");
-               hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
-       }
-
-       return 0;
-
-error:
-
-       kfree(conn_attr->req_ies);
-       conn_attr->req_ies = NULL;
-
-       return result;
-}
-
-static void handle_connect_timeout(struct work_struct *work)
-{
-       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-       struct wilc_vif *vif = msg->vif;
-       int result;
-       struct wid wid;
-       u16 dummy_reason_code = 0;
-       struct host_if_drv *hif_drv = vif->hif_drv;
-
-       if (!hif_drv) {
-               PRINT_ER(vif->ndev, "hif driver is NULL\n");
-               goto out;
-       }
-
-       hif_drv->hif_state = HOST_IF_IDLE;
-
-       if (hif_drv->conn_info.conn_result) {
-               hif_drv->conn_info.conn_result(EVENT_CONN_RESP,
-                                              WILC_MAC_STATUS_DISCONNECTED,
-                                              hif_drv->conn_info.arg);
-
-       } else {
-               PRINT_ER(vif->ndev, "conn_result is NULL\n");
-       }
-
-       wid.id = WID_DISCONNECT;
-       wid.type = WID_CHAR;
-       wid.val = (s8 *)&dummy_reason_code;
-       wid.size = sizeof(char);
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Sending disconnect request\n");
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev, "Failed to send disconect\n");
-
-       hif_drv->conn_info.req_ies_len = 0;
-       kfree(hif_drv->conn_info.req_ies);
-       hif_drv->conn_info.req_ies = NULL;
-
-out:
-       kfree(msg);
-}
-
-void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
-                               struct cfg80211_crypto_settings *crypto)
-{
-       struct wilc_join_bss_param *param;
-       struct ieee80211_p2p_noa_attr noa_attr;
-       u8 rates_len = 0;
-       const u8 *tim_elm, *ssid_elm, *rates_ie, *supp_rates_ie;
-       const u8 *ht_ie, *wpa_ie, *wmm_ie, *rsn_ie;
-       int ret;
-       const struct cfg80211_bss_ies *ies = rcu_dereference(bss->ies);
-
-       param = kzalloc(sizeof(*param), GFP_KERNEL);
-       if (!param)
-               return NULL;
-
-       param->beacon_period = cpu_to_le16(bss->beacon_interval);
-       param->cap_info = cpu_to_le16(bss->capability);
-       param->bss_type = WILC_FW_BSS_TYPE_INFRA;
-       param->ch = ieee80211_frequency_to_channel(bss->channel->center_freq);
-       ether_addr_copy(param->bssid, bss->bssid);
-
-       ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
-       if (ssid_elm) {
-               if (ssid_elm[1] <= IEEE80211_MAX_SSID_LEN)
-                       memcpy(param->ssid, ssid_elm + 2, ssid_elm[1]);
-       }
-
-       tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len);
-       if (tim_elm && tim_elm[1] >= 2)
-               param->dtim_period = tim_elm[3];
-
-       memset(param->p_suites, 0xFF, 3);
-       memset(param->akm_suites, 0xFF, 3);
-
-       rates_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies->data, ies->len);
-       if (rates_ie) {
-               rates_len = rates_ie[1];
-               param->supp_rates[0] = rates_len;
-               memcpy(&param->supp_rates[1], rates_ie + 2, rates_len);
-       }
-
-       supp_rates_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, ies->data,
-                                        ies->len);
-       if (supp_rates_ie) {
-               if (supp_rates_ie[1] > (WILC_MAX_RATES_SUPPORTED - rates_len))
-                       param->supp_rates[0] = WILC_MAX_RATES_SUPPORTED;
-               else
-                       param->supp_rates[0] += supp_rates_ie[1];
-
-               memcpy(&param->supp_rates[rates_len + 1], supp_rates_ie + 2,
-                      (param->supp_rates[0] - rates_len));
-       }
-
-       ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies->data, ies->len);
-       if (ht_ie)
-               param->ht_capable = true;
-
-       ret = cfg80211_get_p2p_attr(ies->data, ies->len,
-                                   IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
-                                   (u8 *)&noa_attr, sizeof(noa_attr));
-       if (ret > 0) {
-               param->tsf_lo = cpu_to_le32(ies->tsf);
-               param->noa_enabled = 1;
-               param->idx = noa_attr.index;
-               if (noa_attr.oppps_ctwindow & IEEE80211_P2P_OPPPS_ENABLE_BIT) {
-                       param->opp_enabled = 1;
-                       param->opp_en.ct_window = noa_attr.oppps_ctwindow;
-                       param->opp_en.cnt = noa_attr.desc[0].count;
-                       param->opp_en.duration = noa_attr.desc[0].duration;
-                       param->opp_en.interval = noa_attr.desc[0].interval;
-                       param->opp_en.start_time = noa_attr.desc[0].start_time;
-               } else {
-                       param->opp_enabled = 0;
-                       param->opp_dis.cnt = noa_attr.desc[0].count;
-                       param->opp_dis.duration = noa_attr.desc[0].duration;
-                       param->opp_dis.interval = noa_attr.desc[0].interval;
-                       param->opp_dis.start_time = noa_attr.desc[0].start_time;
-               }
-       }
-       wmm_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
-                                        WLAN_OUI_TYPE_MICROSOFT_WMM,
-                                        ies->data, ies->len);
-       if (wmm_ie) {
-               struct ieee80211_wmm_param_ie *ie;
-
-               ie = (struct ieee80211_wmm_param_ie *)wmm_ie;
-               if ((ie->oui_subtype == 0 || ie->oui_subtype == 1) &&
-                   ie->version == 1) {
-                       param->wmm_cap = true;
-                       if (ie->qos_info & BIT(7))
-                               param->uapsd_cap = true;
-               }
-       }
-
-       wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
-                                        WLAN_OUI_TYPE_MICROSOFT_WPA,
-                                        ies->data, ies->len);
-       if (wpa_ie) {
-               param->mode_802_11i = 1;
-               param->rsn_found = true;
-       }
-
-       rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, ies->data, ies->len);
-       if (rsn_ie) {
-               int offset = 8;
-
-               param->mode_802_11i = 2;
-               param->rsn_found = true;
-               //extract RSN capabilities
-               offset += (rsn_ie[offset] * 4) + 2;
-               offset += (rsn_ie[offset] * 4) + 2;
-               memcpy(param->rsn_cap, &rsn_ie[offset], 2);
-       }
-
-       if (param->rsn_found) {
-               int i;
-
-               param->rsn_grp_policy = crypto->cipher_group & 0xFF;
-               for (i = 0; i < crypto->n_ciphers_pairwise && i < 3; i++)
-                       param->p_suites[i] = crypto->ciphers_pairwise[i] & 0xFF;
-
-               for (i = 0; i < crypto->n_akm_suites && i < 3; i++)
-                       param->akm_suites[i] = crypto->akm_suites[i] & 0xFF;
-       }
-
-       return (void *)param;
-}
-
-static void handle_rcvd_ntwrk_info(struct work_struct *work)
-{
-       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-       struct wilc_rcvd_net_info *rcvd_info = &msg->body.net_info;
-       struct wilc_user_scan_req *scan_req = &msg->vif->hif_drv->usr_scan_req;
-       const u8 *ch_elm;
-       u8 *ies;
-       int ies_len;
-       size_t offset;
-
-       PRINT_D(msg->vif->ndev, HOSTINF_DBG,
-               "Handling received network info\n");
-
-       if (ieee80211_is_probe_resp(rcvd_info->mgmt->frame_control))
-               offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
-       else if (ieee80211_is_beacon(rcvd_info->mgmt->frame_control))
-               offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
-       else
-               goto done;
-
-       ies = rcvd_info->mgmt->u.beacon.variable;
-       ies_len = rcvd_info->frame_len - offset;
-       if (ies_len <= 0)
-               goto done;
-
-       PRINT_INFO(msg->vif->ndev, HOSTINF_DBG, "New network found\n");
-       /* extract the channel from recevied mgmt frame */
-       ch_elm = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_len);
-       if (ch_elm && ch_elm[1] > 0)
-               rcvd_info->ch = ch_elm[2];
-
-       if (scan_req->scan_result)
-               scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND,
-                                     rcvd_info, scan_req->arg);
-
-done:
-       kfree(rcvd_info->mgmt);
-       kfree(msg);
-}
-
-static void host_int_get_assoc_res_info(struct wilc_vif *vif,
-                                       u8 *assoc_resp_info,
-                                       u32 max_assoc_resp_info_len,
-                                       u32 *rcvd_assoc_resp_info_len)
-{
-       int result;
-       struct wid wid;
-
-       wid.id = WID_ASSOC_RES_INFO;
-       wid.type = WID_STR;
-       wid.val = assoc_resp_info;
-       wid.size = max_assoc_resp_info_len;
-
-       result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result) {
-               *rcvd_assoc_resp_info_len = 0;
-               PRINT_ER(vif->ndev, "Failed to send association response\n");
-               return;
-       }
-
-       *rcvd_assoc_resp_info_len = wid.size;
-}
-
-static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len,
-                                     struct wilc_conn_info *ret_conn_info)
-{
-       u8 *ies;
-       u16 ies_len;
-       struct assoc_resp *res = (struct assoc_resp *)buffer;
-
-       ret_conn_info->status = le16_to_cpu(res->status_code);
-       if (ret_conn_info->status == WLAN_STATUS_SUCCESS) {
-               ies = &buffer[sizeof(*res)];
-               ies_len = buffer_len - sizeof(*res);
-
-               ret_conn_info->resp_ies = kmemdup(ies, ies_len, GFP_KERNEL);
-               if (!ret_conn_info->resp_ies)
-                       return -ENOMEM;
-
-               ret_conn_info->resp_ies_len = ies_len;
-       }
-
-       return 0;
-}
-
-static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
-                                                 u8 mac_status)
-{
-       struct host_if_drv *hif_drv = vif->hif_drv;
-       struct wilc_conn_info *conn_info = &hif_drv->conn_info;
-
-       if (mac_status == WILC_MAC_STATUS_CONNECTED) {
-               u32 assoc_resp_info_len;
-
-               memset(hif_drv->assoc_resp, 0, WILC_MAX_ASSOC_RESP_FRAME_SIZE);
-
-               host_int_get_assoc_res_info(vif, hif_drv->assoc_resp,
-                                           WILC_MAX_ASSOC_RESP_FRAME_SIZE,
-                                           &assoc_resp_info_len);
-
-               PRINT_D(vif->ndev, HOSTINF_DBG,
-                       "Received association response = %d\n",
-                       assoc_resp_info_len);
-               if (assoc_resp_info_len != 0) {
-                       s32 err = 0;
-
-                       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                                  "Parsing association response\n");
-                       err = wilc_parse_assoc_resp_info(hif_drv->assoc_resp,
-                                                        assoc_resp_info_len,
-                                                        conn_info);
-                       if (err)
-                               PRINT_ER(vif->ndev,
-                                        "wilc_parse_assoc_resp_info() returned error %d\n",
-                                        err);
-               }
-       }
-
-       del_timer(&hif_drv->connect_timer);
-       conn_info->conn_result(EVENT_CONN_RESP, mac_status, conn_info->arg);
-
-       if (mac_status == WILC_MAC_STATUS_CONNECTED &&
-           conn_info->status == WLAN_STATUS_SUCCESS) {
-               PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                          "MAC status : CONNECTED and Connect Status : Successful\n");
-               hif_drv->hif_state = HOST_IF_CONNECTED;
-               ether_addr_copy(hif_drv->assoc_bssid, conn_info->bssid);
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-               handle_pwrsave_for_IP(vif, IP_STATE_OBTAINING);
-#endif
-       } else {
-               PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                          "MAC status : %d and Connect Status : %d\n",
-                          mac_status, conn_info->status);
-               hif_drv->hif_state = HOST_IF_IDLE;
-       }
-
-       kfree(conn_info->resp_ies);
-       conn_info->resp_ies = NULL;
-       conn_info->resp_ies_len = 0;
-
-       kfree(conn_info->req_ies);
-       conn_info->req_ies = NULL;
-       conn_info->req_ies_len = 0;
-}
-
-static inline void host_int_handle_disconnect(struct wilc_vif *vif)
-{
-       struct host_if_drv *hif_drv = vif->hif_drv;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                  "Received WILC_MAC_STATUS_DISCONNECTED from the FW\n");
-       if (hif_drv->usr_scan_req.scan_result) {
-               PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                          "\n\n<< Abort the running OBSS Scan >>\n\n");
-               del_timer(&hif_drv->scan_timer);
-               handle_scan_done(vif, SCAN_EVENT_ABORTED);
-       }
-
-       if (hif_drv->conn_info.conn_result) {
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-               handle_pwrsave_for_IP(vif, IP_STATE_DEFAULT);
-#endif
-
-               hif_drv->conn_info.conn_result(EVENT_DISCONN_NOTIF,
-                                              0, hif_drv->conn_info.arg);
-       } else {
-               PRINT_ER(vif->ndev, "Connect result NULL\n");
-       }
-
-       eth_zero_addr(hif_drv->assoc_bssid);
-
-       hif_drv->conn_info.req_ies_len = 0;
-       kfree(hif_drv->conn_info.req_ies);
-       hif_drv->conn_info.req_ies = NULL;
-       hif_drv->hif_state = HOST_IF_IDLE;
-}
-
-static void handle_rcvd_gnrl_async_info(struct work_struct *work)
-{
-       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-       struct wilc_vif *vif = msg->vif;
-       struct wilc_rcvd_mac_info *mac_info = &msg->body.mac_info;
-       struct host_if_drv *hif_drv = vif->hif_drv;
-
-       if (!hif_drv) {
-               netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
-               goto free_msg;
-       }
-
-       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                  "Current State = %d,Received state = %d\n",
-                  hif_drv->hif_state, mac_info->status);
-
-       if (!hif_drv->conn_info.conn_result) {
-               PRINT_ER(vif->ndev, "conn_result is NULL\n");
-               goto free_msg;
-       }
-       if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
-               host_int_parse_assoc_resp_info(vif, mac_info->status);
-       } else if (mac_info->status == WILC_MAC_STATUS_DISCONNECTED) {
-               if (hif_drv->hif_state == HOST_IF_CONNECTED) {
-                       host_int_handle_disconnect(vif);
-               } else if (hif_drv->usr_scan_req.scan_result) {
-                       PRINT_WRN(vif->ndev, HOSTINF_DBG,
-                                 "Received WILC_MAC_STATUS_DISCONNECTED. Abort the running Scan");
-                       del_timer(&hif_drv->scan_timer);
-                       handle_scan_done(vif, SCAN_EVENT_ABORTED);
-               }
-       }
-
-free_msg:
-       kfree(msg);
-}
-
-int wilc_disconnect(struct wilc_vif *vif)
-{
-       struct wid wid;
-       struct host_if_drv *hif_drv = vif->hif_drv;
-       struct wilc_user_scan_req *scan_req;
-       struct wilc_conn_info *conn_info;
-       int result;
-       u16 dummy_reason_code = 0;
-       struct host_if_drv *hif_drv_p2p = get_drv_hndl_by_ifc(vif->wilc,
-                                                             WILC_P2P_IFC);
-       struct host_if_drv *hif_drv_wlan = get_drv_hndl_by_ifc(vif->wilc,
-                                                              WILC_WLAN_IFC);
-
-       if (hif_drv_wlan != NULL) {
-               if (hif_drv_wlan->hif_state == HOST_IF_SCANNING) {
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "Abort Scan. WLAN_IFC is in state [%d]\n",
-                                  hif_drv_wlan->hif_state);
-                       del_timer(&hif_drv_wlan->scan_timer);
-                       handle_scan_done(vif, SCAN_EVENT_ABORTED);
-               }
-       }
-       if (hif_drv_p2p != NULL) {
-               if (hif_drv_p2p->hif_state == HOST_IF_SCANNING) {
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "Abort Scan. P2P_IFC is in state [%d]\n",
-                                  hif_drv_p2p->hif_state);
-                       del_timer(&hif_drv_p2p->scan_timer);
-                       handle_scan_done(vif, SCAN_EVENT_ABORTED);
-               }
-       }
-       wid.id = WID_DISCONNECT;
-       wid.type = WID_CHAR;
-       wid.val = (s8 *)&dummy_reason_code;
-       wid.size = sizeof(char);
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Sending disconnect request\n");
-
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-       handle_pwrsave_for_IP(vif, IP_STATE_DEFAULT);
-#endif
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-
-       if (result) {
-               PRINT_ER(vif->ndev, "Failed to send disconnect\n");
-               return -ENOMEM;
-       }
-
-       scan_req = &hif_drv->usr_scan_req;
-       conn_info = &hif_drv->conn_info;
-
-       if (scan_req->scan_result) {
-               del_timer(&hif_drv->scan_timer);
-               scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg);
-               scan_req->scan_result = NULL;
-       }
-
-       if (conn_info->conn_result) {
-               if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
-                       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                                  "supplicant requested disconnection\n");
-                       del_timer(&hif_drv->connect_timer);
-                       conn_info->conn_result(EVENT_CONN_RESP,
-                                              WILC_MAC_STATUS_DISCONNECTED,
-                                              conn_info->arg);
-
-               } else if (hif_drv->hif_state == HOST_IF_CONNECTED) {
-                       conn_info->conn_result(EVENT_DISCONN_NOTIF,
-                                              WILC_MAC_STATUS_DISCONNECTED,
-                                              conn_info->arg);
-               }
-       } else {
-               PRINT_ER(vif->ndev, "conn_result = NULL\n");
-       }
-
-       hif_drv->hif_state = HOST_IF_IDLE;
-
-       eth_zero_addr(hif_drv->assoc_bssid);
-
-       conn_info->req_ies_len = 0;
-       kfree(conn_info->req_ies);
-       conn_info->req_ies = NULL;
-
-       return 0;
-}
-
-void wilc_resolve_disconnect_aberration(struct wilc_vif *vif)
-{
-       if (!vif->hif_drv)
-               return;
-       if (vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
-           vif->hif_drv->hif_state == HOST_IF_CONNECTING) {
-               PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                          "\n\n<< correcting Supplicant state machine >>\n\n");
-               wilc_disconnect(vif);
-       }
-}
-
-int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
-{
-       struct wid wid_list[5];
-       u32 wid_cnt = 0, result;
-
-       wid_list[wid_cnt].id = WID_LINKSPEED;
-       wid_list[wid_cnt].type = WID_CHAR;
-       wid_list[wid_cnt].size = sizeof(char);
-       wid_list[wid_cnt].val = (s8 *)&stats->link_speed;
-       wid_cnt++;
-
-       wid_list[wid_cnt].id = WID_RSSI;
-       wid_list[wid_cnt].type = WID_CHAR;
-       wid_list[wid_cnt].size = sizeof(char);
-       wid_list[wid_cnt].val = (s8 *)&stats->rssi;
-       wid_cnt++;
-
-       wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
-       wid_list[wid_cnt].type = WID_INT;
-       wid_list[wid_cnt].size = sizeof(u32);
-       wid_list[wid_cnt].val = (s8 *)&stats->tx_cnt;
-       wid_cnt++;
-
-       wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT;
-       wid_list[wid_cnt].type = WID_INT;
-       wid_list[wid_cnt].size = sizeof(u32);
-       wid_list[wid_cnt].val = (s8 *)&stats->rx_cnt;
-       wid_cnt++;
-
-       wid_list[wid_cnt].id = WID_FAILED_COUNT;
-       wid_list[wid_cnt].type = WID_INT;
-       wid_list[wid_cnt].size = sizeof(u32);
-       wid_list[wid_cnt].val = (s8 *)&stats->tx_fail_cnt;
-       wid_cnt++;
-
-       result = wilc_send_config_pkt(vif, WILC_GET_CFG, wid_list,
-                                     wid_cnt,
-                                     wilc_get_vif_idx(vif));
-
-       if (result) {
-               PRINT_ER(vif->ndev, "Failed to send scan parameters\n");
-               return result;
-       }
-
-       if (stats->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
-           stats->link_speed != DEFAULT_LINK_SPEED) {
-               PRINT_INFO(vif->ndev, HOSTINF_DBG, "Enable TCP filter\n");
-               wilc_enable_tcp_ack_filter(vif, true);
-       } else if (stats->link_speed != DEFAULT_LINK_SPEED) {
-               PRINT_INFO(vif->ndev, HOSTINF_DBG, "Disable TCP filter %d\n",
-                          stats->link_speed);
-               wilc_enable_tcp_ack_filter(vif, false);
-       }
-
-       return result;
-}
-
-static void handle_get_statistics(struct work_struct *work)
-{
-       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-       struct wilc_vif *vif = msg->vif;
-       struct rf_info *stats = (struct rf_info *)msg->body.data;
-
-       wilc_get_statistics(vif, stats);
-       kfree(msg);
-}
-
-static void wilc_hif_pack_sta_param(struct wilc_vif *vif, u8 *cur_byte,
-                                   const u8 *mac,
-                                   struct station_parameters *params)
-{
-       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Packing STA params\n");
-       ether_addr_copy(cur_byte, mac);
-       cur_byte +=  ETH_ALEN;
-
-       put_unaligned_le16(params->aid, cur_byte);
-       cur_byte += 2;
-
-       *cur_byte++ = params->supported_rates_len;
-       if (params->supported_rates_len > 0)
-               memcpy(cur_byte, params->supported_rates,
-                      params->supported_rates_len);
-       cur_byte += params->supported_rates_len;
-
-       if (params->ht_capa) {
-               *cur_byte++ = true;
-               memcpy(cur_byte, &params->ht_capa,
-                      sizeof(struct ieee80211_ht_cap));
-       } else {
-               *cur_byte++ = false;
-       }
-       cur_byte += sizeof(struct ieee80211_ht_cap);
-
-       put_unaligned_le16(params->sta_flags_mask, cur_byte);
-       cur_byte += 2;
-       put_unaligned_le16(params->sta_flags_set, cur_byte);
-}
-
-static int handle_remain_on_chan(struct wilc_vif *vif,
-                                struct wilc_remain_ch *hif_remain_ch)
-{
-       int result;
-       u8 remain_on_chan_flag;
-       struct wid wid;
-       struct host_if_drv *hif_drv = vif->hif_drv;
-       struct host_if_drv *hif_drv_p2p = get_drv_hndl_by_ifc(vif->wilc,
-                                                             WILC_P2P_IFC);
-       struct host_if_drv *hif_drv_wlan = get_drv_hndl_by_ifc(vif->wilc,
-                                                              WILC_WLAN_IFC);
-
-       if (!hif_drv) {
-               PRINT_ER(vif->ndev, "Driver is null\n");
-               return -EFAULT;
-       }
-
-       if (hif_drv_p2p != NULL) {
-               if (hif_drv_p2p->hif_state == HOST_IF_SCANNING) {
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "IFC busy scanning P2P_IFC state %d\n",
-                                  hif_drv_p2p->hif_state);
-                       return -EBUSY;
-               } else if ((hif_drv_p2p->hif_state != HOST_IF_IDLE) &&
-               (hif_drv_p2p->hif_state != HOST_IF_CONNECTED)) {
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "IFC busy connecting. P2P_IFC state %d\n",
-                                  hif_drv_p2p->hif_state);
-                       return -EBUSY;
-               }
-       }
-       if (hif_drv_wlan != NULL) {
-               if (hif_drv_wlan->hif_state == HOST_IF_SCANNING) {
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "IFC busy scanning. WLAN_IFC state %d\n",
-                                  hif_drv_wlan->hif_state);
-                       return -EBUSY;
-               } else if ((hif_drv_wlan->hif_state != HOST_IF_IDLE) &&
-               (hif_drv_wlan->hif_state != HOST_IF_CONNECTED)) {
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "IFC busy connecting. WLAN_IFC %d\n",
-                                  hif_drv_wlan->hif_state);
-                       return -EBUSY;
-               }
-       }
-
-       if (vif->connecting) {
-               PRINT_INFO(vif->ndev, GENERIC_DBG,
-                          "Don't do scan in (CONNECTING) state\n");
-               return -EBUSY;
-       }
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-       if (vif->obtaining_ip) {
-               PRINT_INFO(vif->ndev, GENERIC_DBG,
-                          "Don't obss scan until IP adresss is obtained\n");
-               return -EBUSY;
-       }
-#endif
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                  "Setting channel [%d] duration[%d] [%llu]\n",
-                  hif_remain_ch->ch, hif_remain_ch->duration,
-                  hif_remain_ch->cookie);
-       remain_on_chan_flag = true;
-       wid.id = WID_REMAIN_ON_CHAN;
-       wid.type = WID_STR;
-       wid.size = 2;
-       wid.val = kmalloc(wid.size, GFP_KERNEL);
-       if (!wid.val)
-               return -ENOMEM;
-
-       wid.val[0] = remain_on_chan_flag;
-       wid.val[1] = (s8)hif_remain_ch->ch;
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       kfree(wid.val);
-       if (result) {
-               PRINT_ER(vif->ndev, "Failed to set remain on channel\n");
-               return -EBUSY;
-       }
-
-       hif_drv->remain_on_ch.arg = hif_remain_ch->arg;
-       hif_drv->remain_on_ch.expired = hif_remain_ch->expired;
-       hif_drv->remain_on_ch.ch = hif_remain_ch->ch;
-       hif_drv->remain_on_ch.cookie = hif_remain_ch->cookie;
-       hif_drv->hif_state = HOST_IF_P2P_LISTEN;
-
-       hif_drv->remain_on_ch_timer_vif = vif;
-
-       return result;
-}
-
-static void handle_listen_state_expired(struct work_struct *work)
-{
-       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-       struct wilc_vif *vif = msg->vif;
-       struct wilc_remain_ch *hif_remain_ch = &msg->body.remain_on_ch;
-       u8 remain_on_chan_flag;
-       struct wid wid;
-       int result;
-       struct host_if_drv *hif_drv = vif->hif_drv;
-       u8 null_bssid[6] = {0};
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG, "CANCEL REMAIN ON CHAN\n");
-
-       if (hif_drv->hif_state == HOST_IF_P2P_LISTEN) {
-               remain_on_chan_flag = false;
-               wid.id = WID_REMAIN_ON_CHAN;
-               wid.type = WID_STR;
-               wid.size = 2;
-               wid.val = kmalloc(wid.size, GFP_KERNEL);
-
-               if (!wid.val) {
-                       PRINT_ER(vif->ndev, "Failed to allocate memory\n");
-                       goto free_msg;
-               }
-
-               wid.val[0] = remain_on_chan_flag;
-               wid.val[1] = WILC_FALSE_FRMWR_CHANNEL;
-
-               result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                             wilc_get_vif_idx(vif));
-               kfree(wid.val);
-               if (result != 0) {
-                       PRINT_ER(vif->ndev, "Failed to set remain channel\n");
-                       goto free_msg;
-               }
-
-               if (hif_drv->remain_on_ch.expired)
-                       hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
-                                                     hif_remain_ch->cookie);
-
-               if (memcmp(hif_drv->assoc_bssid, null_bssid, ETH_ALEN) == 0)
-                       hif_drv->hif_state = HOST_IF_IDLE;
-               else
-                       hif_drv->hif_state = HOST_IF_CONNECTED;
-       } else {
-               PRINT_D(vif->ndev, GENERIC_DBG,  "Not in listen state\n");
-       }
-
-free_msg:
-       kfree(msg);
-}
-
-#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
-static void listen_timer_cb(struct timer_list *t)
-#else
-static void listen_timer_cb(unsigned long arg)
-#endif
-{
-#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
-       struct host_if_drv *hif_drv = from_timer(hif_drv, t,
-                                                     remain_on_ch_timer);
-#else
-       struct host_if_drv *hif_drv = (struct host_if_drv *)arg;
-#endif
-       struct wilc_vif *vif = hif_drv->remain_on_ch_timer_vif;
-       int result;
-       struct host_if_msg *msg;
-
-       del_timer(&vif->hif_drv->remain_on_ch_timer);
-
-       msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
-       if (IS_ERR(msg))
-               return;
-
-       msg->body.remain_on_ch.cookie = vif->hif_drv->remain_on_ch.cookie;
-
-       result = wilc_enqueue_work(msg);
-       if (result) {
-               PRINT_ER(vif->ndev, "wilc_mq_send fail\n");
-               kfree(msg);
-       }
-}
-
-static void handle_set_mcast_filter(struct work_struct *work)
-{
-       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-       struct wilc_vif *vif = msg->vif;
-       struct wilc_set_multicast *set_mc = &msg->body.mc_info;
-       int result;
-       struct wid wid;
-       u8 *cur_byte;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Setup Multicast Filter\n");
-
-       wid.id = WID_SETUP_MULTICAST_FILTER;
-       wid.type = WID_BIN;
-       wid.size = sizeof(struct wilc_set_multicast) + (set_mc->cnt * ETH_ALEN);
-       wid.val = kmalloc(wid.size, GFP_KERNEL);
-       if (!wid.val)
-               goto error;
-
-       cur_byte = wid.val;
-       put_unaligned_le32(set_mc->enabled, cur_byte);
-       cur_byte += 4;
-
-       put_unaligned_le32(set_mc->cnt, cur_byte);
-       cur_byte += 4;
-
-       if (set_mc->cnt > 0 && set_mc->mc_list)
-               memcpy(cur_byte, set_mc->mc_list, set_mc->cnt * ETH_ALEN);
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev, "Failed to send setup multicast\n");
-
-error:
-       kfree(set_mc->mc_list);
-       kfree(wid.val);
-       kfree(msg);
-}
-
-void wilc_set_wowlan_trigger(struct wilc_vif *vif, u8 wowlan_trigger)
-{
-       int ret;
-       struct wid wid;
-
-       wid.id = WID_WOWLAN_TRIGGER;
-       wid.type = WID_CHAR;
-       wid.val = &wowlan_trigger;
-       wid.size = sizeof(s8);
-
-       ret = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                  wilc_get_vif_idx(vif));
-
-       if (ret)
-               PRINT_ER(vif->ndev,
-                        "Failed to send wowlan trigger config packet\n");
-}
-
-static void handle_scan_timer(struct work_struct *work)
-{
-       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-       int ret;
-
-       PRINT_INFO(msg->vif->ndev, HOSTINF_DBG, "handling scan timer\n");
-       ret = handle_scan_done(msg->vif, SCAN_EVENT_ABORTED);
-       if (ret)
-               PRINT_ER(msg->vif->ndev, "Failed to handle scan done\n");
-       kfree(msg);
-}
-
-static void handle_scan_complete(struct work_struct *work)
-{
-       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-
-       del_timer(&msg->vif->hif_drv->scan_timer);
-       PRINT_INFO(msg->vif->ndev, HOSTINF_DBG, "scan completed\n");
-
-       handle_scan_done(msg->vif, SCAN_EVENT_DONE);
-
-       kfree(msg);
-}
-
-#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
-static void timer_scan_cb(struct timer_list *t)
-#else
-static void timer_scan_cb(unsigned long arg)
-#endif
-{
-#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
-       struct host_if_drv *hif_drv = from_timer(hif_drv, t, scan_timer);
-#else
-       struct host_if_drv *hif_drv = (struct host_if_drv *)arg;
-#endif
-       struct wilc_vif *vif = hif_drv->scan_timer_vif;
-       struct host_if_msg *msg;
-       int result;
-
-       msg = wilc_alloc_work(vif, handle_scan_timer, false);
-       if (IS_ERR(msg))
-               return;
-
-       result = wilc_enqueue_work(msg);
-       if (result)
-               kfree(msg);
-}
-
-#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
-static void timer_connect_cb(struct timer_list *t)
-#else
-static void timer_connect_cb(unsigned long arg)
-#endif
-{
-#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
-       struct host_if_drv *hif_drv = from_timer(hif_drv, t, connect_timer);
-#else
-       struct host_if_drv *hif_drv = (struct host_if_drv *)arg;
-#endif
-       struct wilc_vif *vif = hif_drv->connect_timer_vif;
-       struct host_if_msg *msg;
-       int result;
-
-       msg = wilc_alloc_work(vif, handle_connect_timeout, false);
-       if (IS_ERR(msg))
-               return;
-
-       result = wilc_enqueue_work(msg);
-       if (result)
-               kfree(msg);
-}
-
-signed int wilc_send_buffered_eap(struct wilc_vif *vif,
-                                 void (*deliver_to_stack)(struct wilc_vif *,
-                                                          u8 *, u32, u32, u8),
-                                 void (*eap_buf_param)(void *), u8 *buff,
-                                 unsigned int size, unsigned int pkt_offset,
-                                 void *user_arg)
-{
-       int result;
-       struct host_if_msg *msg;
-
-       if (!vif || !deliver_to_stack || !eap_buf_param)
-               return -EFAULT;
-
-       msg = wilc_alloc_work(vif, handle_send_buffered_eap, false);
-       if (IS_ERR(msg))
-               return PTR_ERR(msg);
-       msg->body.send_buff_eap.deliver_to_stack = deliver_to_stack;
-       msg->body.send_buff_eap.eap_buf_param = eap_buf_param;
-       msg->body.send_buff_eap.size = size;
-       msg->body.send_buff_eap.pkt_offset = pkt_offset;
-       msg->body.send_buff_eap.buff = kmalloc(size + pkt_offset,
-                                                 GFP_ATOMIC);
-       memcpy(msg->body.send_buff_eap.buff, buff, size + pkt_offset);
-       msg->body.send_buff_eap.user_arg = user_arg;
-
-       result = wilc_enqueue_work(msg);
-       if (result) {
-               PRINT_ER(vif->ndev, "enqueue work failed\n");
-               kfree(msg->body.send_buff_eap.buff);
-               kfree(msg);
-       }
-       return result;
-}
-
-int wilc_remove_wep_key(struct wilc_vif *vif, u8 index)
-{
-       struct wid wid;
-       int result;
-
-       wid.id = WID_REMOVE_WEP_KEY;
-       wid.type = WID_STR;
-       wid.size = sizeof(char);
-       wid.val = &index;
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev,
-                        "Failed to send remove wep key config packet\n");
-       return result;
-}
-
-int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index)
-{
-       struct wid wid;
-       int result;
-
-       wid.id = WID_KEY_ID;
-       wid.type = WID_CHAR;
-       wid.size = sizeof(char);
-       wid.val = &index;
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev,
-                        "Failed to send wep default key config packet\n");
-
-       return result;
-}
-
-int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
-                            u8 index)
-{
-       struct wid wid;
-       int result;
-       struct wilc_wep_key *wep_key;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Handling WEP key\n");
-       wid.id = WID_ADD_WEP_KEY;
-       wid.type = WID_STR;
-       wid.size = sizeof(*wep_key) + len;
-       wep_key = kzalloc(wid.size, GFP_KERNEL);
-       if (!wep_key) {
-               PRINT_ER(vif->ndev, "No buffer to send Key\n");
-               return -ENOMEM;
-       }
-       wid.val = (u8 *)wep_key;
-
-       wep_key->index = index;
-       wep_key->key_len = len;
-       memcpy(wep_key->key, key, len);
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               netdev_err(vif->ndev,
-                          "Failed to add wep key config packet\n");
-
-       kfree(wep_key);
-       return result;
-}
-
-int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
-                           u8 index, u8 mode, enum authtype auth_type)
-{
-       struct wid wid_list[3];
-       int result;
-       struct wilc_wep_key *wep_key;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Handling WEP key index: %d\n",
-                  index);
-       wid_list[0].id = WID_11I_MODE;
-       wid_list[0].type = WID_CHAR;
-       wid_list[0].size = sizeof(char);
-       wid_list[0].val = &mode;
-
-       wid_list[1].id = WID_AUTH_TYPE;
-       wid_list[1].type = WID_CHAR;
-       wid_list[1].size = sizeof(char);
-       wid_list[1].val = (s8 *)&auth_type;
-
-       wid_list[2].id = WID_WEP_KEY_VALUE;
-       wid_list[2].type = WID_STR;
-       wid_list[2].size = sizeof(*wep_key) + len;
-       wep_key = kzalloc(wid_list[2].size, GFP_KERNEL);
-       if (!wep_key) {
-               PRINT_ER(vif->ndev, "No buffer to send Key\n");
-               return -ENOMEM;
-       }
-
-       wid_list[2].val = (u8 *)wep_key;
-
-       wep_key->index = index;
-       wep_key->key_len = len;
-       memcpy(wep_key->key, key, len);
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
-                                     ARRAY_SIZE(wid_list),
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev,
-                        "Failed to add wep ap key config packet\n");
-
-       kfree(wep_key);
-       return result;
-}
-
-int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
-                const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
-                u8 mode, u8 cipher_mode, u8 index)
-{
-       int result = 0;
-       u8 t_key_len = ptk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
-
-       if (mode == WILC_AP_MODE) {
-               struct wid wid_list[2];
-               struct wilc_ap_wpa_ptk *key_buf;
-
-               wid_list[0].id = WID_11I_MODE;
-               wid_list[0].type = WID_CHAR;
-               wid_list[0].size = sizeof(char);
-               wid_list[0].val = (s8 *)&cipher_mode;
-
-               key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
-               if (!key_buf) {
-                       PRINT_ER(vif->ndev,
-                                "NO buffer to keep Key buffer - AP\n");
-                       return -ENOMEM;
-               }
-               ether_addr_copy(key_buf->mac_addr, mac_addr);
-               key_buf->index = index;
-               key_buf->key_len = t_key_len;
-               memcpy(&key_buf->key[0], ptk, ptk_key_len);
-
-               if (rx_mic)
-                       memcpy(&key_buf->key[ptk_key_len], rx_mic,
-                              WILC_RX_MIC_KEY_LEN);
-
-               if (tx_mic)
-                       memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
-                              tx_mic, WILC_TX_MIC_KEY_LEN);
-
-               wid_list[1].id = WID_ADD_PTK;
-               wid_list[1].type = WID_STR;
-               wid_list[1].size = sizeof(*key_buf) + t_key_len;
-               wid_list[1].val = (u8 *)key_buf;
-               result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
-                                             ARRAY_SIZE(wid_list),
-                                             wilc_get_vif_idx(vif));
-               kfree(key_buf);
-       } else if (mode == WILC_STATION_MODE) {
-               struct wid wid;
-               struct wilc_sta_wpa_ptk *key_buf;
-
-               key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
-               if (!key_buf) {
-                       PRINT_ER(vif->ndev,
-                                "No buffer to keep Key buffer - Station\n");
-                       return -ENOMEM;
-               }
-
-               ether_addr_copy(key_buf->mac_addr, mac_addr);
-               key_buf->key_len = t_key_len;
-               memcpy(&key_buf->key[0], ptk, ptk_key_len);
-
-               if (rx_mic)
-                       memcpy(&key_buf->key[ptk_key_len], rx_mic,
-                              WILC_RX_MIC_KEY_LEN);
-
-               if (tx_mic)
-                       memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
-                              tx_mic, WILC_TX_MIC_KEY_LEN);
-
-               wid.id = WID_ADD_PTK;
-               wid.type = WID_STR;
-               wid.size = sizeof(*key_buf) + t_key_len;
-               wid.val = (s8 *)key_buf;
-               result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                             wilc_get_vif_idx(vif));
-               kfree(key_buf);
-       }
-
-       return result;
-}
-
-int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
-                   u8 index, u32 key_rsc_len, const u8 *key_rsc,
-                   const u8 *rx_mic, const u8 *tx_mic, u8 mode,
-                   u8 cipher_mode)
-{
-       int result = 0;
-       struct wilc_gtk_key *gtk_key;
-       int t_key_len = gtk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
-
-       gtk_key = kzalloc(sizeof(*gtk_key) + t_key_len, GFP_KERNEL);
-       if (!gtk_key) {
-               PRINT_ER(vif->ndev, "No buffer to send GTK Key\n");
-               return -ENOMEM;
-       }
-
-       /* fill bssid value only in station mode */
-       if (mode == WILC_STATION_MODE &&
-           vif->hif_drv->hif_state == HOST_IF_CONNECTED)
-               memcpy(gtk_key->mac_addr, vif->hif_drv->assoc_bssid, ETH_ALEN);
-
-       if (key_rsc)
-               memcpy(gtk_key->rsc, key_rsc, 8);
-       gtk_key->index = index;
-       gtk_key->key_len = t_key_len;
-       memcpy(&gtk_key->key[0], rx_gtk, gtk_key_len);
-
-       if (rx_mic)
-               memcpy(&gtk_key->key[gtk_key_len], rx_mic, WILC_RX_MIC_KEY_LEN);
-
-       if (tx_mic)
-               memcpy(&gtk_key->key[gtk_key_len + WILC_RX_MIC_KEY_LEN],
-                      tx_mic, WILC_TX_MIC_KEY_LEN);
-
-       if (mode == WILC_AP_MODE) {
-               struct wid wid_list[2];
-
-               wid_list[0].id = WID_11I_MODE;
-               wid_list[0].type = WID_CHAR;
-               wid_list[0].size = sizeof(char);
-               wid_list[0].val = (s8 *)&cipher_mode;
-
-               wid_list[1].id = WID_ADD_RX_GTK;
-               wid_list[1].type = WID_STR;
-               wid_list[1].size = sizeof(*gtk_key) + t_key_len;
-               wid_list[1].val = (u8 *)gtk_key;
-
-               result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
-                                             ARRAY_SIZE(wid_list),
-                                             wilc_get_vif_idx(vif));
-               kfree(gtk_key);
-       } else if (mode == WILC_STATION_MODE) {
-               struct wid wid;
-
-               wid.id = WID_ADD_RX_GTK;
-               wid.type = WID_STR;
-               wid.size = sizeof(*gtk_key) + t_key_len;
-               wid.val = (u8 *)gtk_key;
-               result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                             wilc_get_vif_idx(vif));
-               kfree(gtk_key);
-       }
-
-       return result;
-}
-
-int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid)
-{
-       struct wid wid;
-
-       wid.id = WID_PMKID_INFO;
-       wid.type = WID_STR;
-       wid.size = (pmkid->numpmkid * sizeof(struct wilc_pmkid)) + 1;
-       wid.val = (u8 *)pmkid;
-
-       return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-}
-
-int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
-{
-       int result;
-       struct wid wid;
-
-       wid.id = WID_MAC_ADDR;
-       wid.type = WID_STR;
-       wid.size = ETH_ALEN;
-       wid.val = mac_addr;
-
-       result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               netdev_err(vif->ndev, "Failed to get mac address\n");
-
-       return result;
-}
-
-int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr)
-{
-       struct wid wid;
-       int result;
-
-       wid.id = WID_MAC_ADDR;
-       wid.type = WID_STR;
-       wid.size = ETH_ALEN;
-       wid.val = mac_addr;
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev, "Failed to set mac address\n");
-
-       return result;
-}
-
-int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
-                     size_t ies_len)
-{
-       int result;
-       struct host_if_drv *hif_drv = vif->hif_drv;
-       struct wilc_conn_info *conn_info = &hif_drv->conn_info;
-
-       if (bssid)
-               ether_addr_copy(conn_info->bssid, bssid);
-
-       if (ies) {
-               conn_info->req_ies_len = ies_len;
-               conn_info->req_ies = kmemdup(ies, ies_len, GFP_KERNEL);
-               if (!conn_info->req_ies)
-                       return -ENOMEM;
-       }
-
-       result = wilc_send_connect_wid(vif);
-       if (result) {
-               PRINT_ER(vif->ndev, "Failed to send connect wid\n");
-               goto free_ies;
-       }
-
-#if KERNEL_VERSION(4, 15, 0) > LINUX_VERSION_CODE
-       hif_drv->connect_timer.data = (unsigned long)hif_drv;
-#endif
-       hif_drv->connect_timer_vif = vif;
-       mod_timer(&hif_drv->connect_timer,
-                 jiffies + msecs_to_jiffies(WILC_HIF_CONNECT_TIMEOUT_MS));
-
-       return 0;
-
-free_ies:
-       kfree(conn_info->req_ies);
-
-       return result;
-}
-
-int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
-{
-       struct wid wid;
-       int result;
-
-       wid.id = WID_CURRENT_CHANNEL;
-       wid.type = WID_CHAR;
-       wid.size = sizeof(char);
-       wid.val = &channel;
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev, "Failed to set channel\n");
-
-       return result;
-}
-
-int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
-                            u8 ifc_id)
-{
-       struct wid wid;
-       struct host_if_drv *hif_drv = vif->hif_drv;
-       int result;
-       struct wilc_drv_handler drv;
-
-       if (!hif_drv)
-               return -EFAULT;
-
-       wid.id = WID_SET_DRV_HANDLER;
-       wid.type = WID_STR;
-       wid.size = sizeof(drv);
-       wid.val = (u8 *)&drv;
-
-       drv.handler = cpu_to_le32(index);
-       drv.mode = (ifc_id | (mode << 1));
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     hif_drv->driver_handler_id);
-       if (result)
-               PRINT_ER(vif->ndev, "Failed to set driver handler\n");
-
-       return result;
-}
-
-int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode)
-{
-       struct wid wid;
-       struct wilc_op_mode op_mode;
-       int result;
-
-       wid.id = WID_SET_OPERATION_MODE;
-       wid.type = WID_INT;
-       wid.size = sizeof(op_mode);
-       wid.val = (u8 *)&op_mode;
-
-       op_mode.mode = cpu_to_le32(mode);
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev, "Failed to set operation mode\n");
-
-       return result;
-}
-
-s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val)
-{
-       struct wid wid;
-       s32 result;
-
-       wid.id = WID_SET_STA_MAC_INACTIVE_TIME;
-       wid.type = WID_STR;
-       wid.size = ETH_ALEN;
-       wid.val = kzalloc(wid.size, GFP_KERNEL);
-       if (!wid.val) {
-               PRINT_ER(vif->ndev, "Failed to allocate buffer\n");
-               return -ENOMEM;
-       }
-
-       ether_addr_copy(wid.val, mac);
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       kfree(wid.val);
-       if (result) {
-               PRINT_ER(vif->ndev, "Failed to set inactive mac\n");
-               return result;
-       }
-
-       wid.id = WID_GET_INACTIVE_TIME;
-       wid.type = WID_INT;
-       wid.val = (s8 *)out_val;
-       wid.size = sizeof(u32);
-       result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev, "Failed to get inactive time\n");
-
-       PRINT_INFO(vif->ndev, CFG80211_DBG, "Getting inactive time : %d\n",
-                  *out_val);
-
-       return result;
-}
-
-int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
-{
-       struct wid wid;
-       int result;
-
-       if (!rssi_level) {
-               PRINT_ER(vif->ndev, "RSS pointer value is null\n");
-               return -EFAULT;
-       }
-
-       wid.id = WID_RSSI;
-       wid.type = WID_CHAR;
-       wid.size = sizeof(char);
-       wid.val = rssi_level;
-       result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               netdev_err(vif->ndev, "Failed to get RSSI value\n");
-
-       return result;
-}
-
-int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats)
-{
-       int result;
-       struct host_if_msg *msg;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG, " getting async statistics\n");
-       msg = wilc_alloc_work(vif, handle_get_statistics, false);
-       if (IS_ERR(msg))
-               return PTR_ERR(msg);
-
-       msg->body.data = (char *)stats;
-
-       result = wilc_enqueue_work(msg);
-       if (result) {
-               PRINT_ER(vif->ndev, "enqueue work failed\n");
-               kfree(msg);
-               return result;
-       }
-
-       return result;
-}
-
-int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *param)
-{
-       struct wid wid_list[4];
-       int i = 0;
-
-       if (param->flag & WILC_CFG_PARAM_RETRY_SHORT) {
-               wid_list[i].id = WID_SHORT_RETRY_LIMIT;
-               wid_list[i].val = (s8 *)&param->short_retry_limit;
-               wid_list[i].type = WID_SHORT;
-               wid_list[i].size = sizeof(u16);
-               i++;
-       }
-       if (param->flag & WILC_CFG_PARAM_RETRY_LONG) {
-               wid_list[i].id = WID_LONG_RETRY_LIMIT;
-               wid_list[i].val = (s8 *)&param->long_retry_limit;
-               wid_list[i].type = WID_SHORT;
-               wid_list[i].size = sizeof(u16);
-               i++;
-       }
-       if (param->flag & WILC_CFG_PARAM_FRAG_THRESHOLD) {
-               wid_list[i].id = WID_FRAG_THRESHOLD;
-               wid_list[i].val = (s8 *)&param->frag_threshold;
-               wid_list[i].type = WID_SHORT;
-               wid_list[i].size = sizeof(u16);
-               i++;
-       }
-       if (param->flag & WILC_CFG_PARAM_RTS_THRESHOLD) {
-               wid_list[i].id = WID_RTS_THRESHOLD;
-               wid_list[i].val = (s8 *)&param->rts_threshold;
-               wid_list[i].type = WID_SHORT;
-               wid_list[i].size = sizeof(u16);
-               i++;
-       }
-
-       return wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
-                                     i, wilc_get_vif_idx(vif));
-}
-
-#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
-static void get_periodic_rssi(struct timer_list *t)
-#else
-static void get_periodic_rssi(unsigned long arg)
-#endif
-{
-#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
-       struct wilc_vif *vif = from_timer(vif, t, periodic_rssi);
-#else
-       struct wilc_vif *vif = (struct wilc_vif *)arg;
-#endif
-
-       if (!vif->hif_drv) {
-               PRINT_ER(vif->ndev, "hif driver is NULL\n");
-               return;
-       }
-
-       if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
-               wilc_get_stats_async(vif, &vif->periodic_stats);
-
-       mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
-}
-
-int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
-{
-       struct host_if_drv *hif_drv;
-       struct wilc_vif *vif = netdev_priv(dev);
-       struct wilc *wilc = vif->wilc;
-       int i;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                  "Initializing host interface for client %d\n",
-                  wilc->clients_count + 1);
-
-       hif_drv  = kzalloc(sizeof(*hif_drv), GFP_KERNEL);
-       if (!hif_drv) {
-               PRINT_ER(dev, "hif driver is NULL\n");
-               return -ENOMEM;
-       }
-       *hif_drv_handler = hif_drv;
-       for (i = 0; i < wilc->vif_num; i++)
-               if (dev == wilc->vif[i]->ndev) {
-                       wilc->vif[i]->hif_drv = hif_drv;
-                       hif_drv->driver_handler_id = i + 1;
-                       break;
-               }
-
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-       vif->obtaining_ip = false;
-#endif
-
-       if (wilc->clients_count == 0)
-               mutex_init(&wilc->deinit_lock);
-
-       #if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
-               timer_setup(&vif->periodic_rssi, get_periodic_rssi, 0);
-       #else
-               setup_timer(&vif->periodic_rssi, get_periodic_rssi,
-                           (unsigned long)vif);
-       #endif
-               mod_timer(&vif->periodic_rssi,
-                         jiffies + msecs_to_jiffies(5000));
-
-#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
-       timer_setup(&hif_drv->scan_timer, timer_scan_cb, 0);
-       timer_setup(&hif_drv->connect_timer, timer_connect_cb, 0);
-       timer_setup(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0);
-#else
-       setup_timer(&hif_drv->scan_timer, timer_scan_cb, 0);
-       setup_timer(&hif_drv->connect_timer, timer_connect_cb, 0);
-       setup_timer(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0);
-#endif
-
-       hif_drv->hif_state = HOST_IF_IDLE;
-
-       hif_drv->p2p_timeout = 0;
-
-       wilc->clients_count++;
-
-       return 0;
-}
-
-int wilc_deinit(struct wilc_vif *vif)
-{
-       int result = 0;
-       struct host_if_drv *hif_drv = vif->hif_drv;
-
-       if (!hif_drv) {
-               PRINT_ER(vif->ndev, "hif driver is NULL\n");
-               return -EFAULT;
-       }
-
-       mutex_lock(&vif->wilc->deinit_lock);
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                  "De-initializing host interface for client %d\n",
-                  vif->wilc->clients_count);
-
-       del_timer_sync(&hif_drv->scan_timer);
-       del_timer_sync(&hif_drv->connect_timer);
-       del_timer_sync(&vif->periodic_rssi);
-       del_timer_sync(&hif_drv->remain_on_ch_timer);
-
-       if (hif_drv->usr_scan_req.scan_result) {
-               hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL,
-                                                 hif_drv->usr_scan_req.arg);
-               hif_drv->usr_scan_req.scan_result = NULL;
-       }
-
-       hif_drv->hif_state = HOST_IF_IDLE;
-
-       kfree(hif_drv);
-       vif->hif_drv = NULL;
-
-       vif->wilc->clients_count--;
-       mutex_unlock(&vif->wilc->deinit_lock);
-       return result;
-}
-
-void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
-{
-       int result;
-       struct host_if_msg *msg;
-       int id;
-       struct host_if_drv *hif_drv;
-       struct wilc_vif *vif;
-
-       id = get_unaligned_le32(&buffer[length - 4]);
-       vif = wilc_get_vif_from_idx(wilc, id);
-       if (!vif)
-               return;
-       hif_drv = vif->hif_drv;
-
-       if (!hif_drv) {
-               PRINT_ER(vif->ndev, "driver not init[%p]\n", hif_drv);
-               return;
-       }
-
-       msg = wilc_alloc_work(vif, handle_rcvd_ntwrk_info, false);
-       if (IS_ERR(msg))
-               return;
-
-       msg->body.net_info.frame_len = get_unaligned_le16(&buffer[6]) - 1;
-       msg->body.net_info.rssi = buffer[8];
-       msg->body.net_info.mgmt = kmemdup(&buffer[9],
-                                         msg->body.net_info.frame_len,
-                                         GFP_KERNEL);
-       if (!msg->body.net_info.mgmt) {
-               kfree(msg);
-               return;
-       }
-
-       result = wilc_enqueue_work(msg);
-       if (result) {
-               PRINT_ER(vif->ndev, "message parameters (%d)\n", result);
-               kfree(msg->body.net_info.mgmt);
-               kfree(msg);
-       }
-}
-
-void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length)
-{
-       int result;
-       struct host_if_msg *msg;
-       int id;
-       struct host_if_drv *hif_drv;
-       struct wilc_vif *vif;
-
-       mutex_lock(&wilc->deinit_lock);
-
-       id = get_unaligned_le32(&buffer[length - 4]);
-       vif = wilc_get_vif_from_idx(wilc, id);
-       if (!vif) {
-               mutex_unlock(&wilc->deinit_lock);
-               return;
-       }
-       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                  "General asynchronous info packet received\n");
-
-       hif_drv = vif->hif_drv;
-
-       if (!hif_drv) {
-               PRINT_ER(vif->ndev, "hif driver is NULL\n");
-               mutex_unlock(&wilc->deinit_lock);
-               return;
-       }
-
-       if (!hif_drv->conn_info.conn_result) {
-               PRINT_ER(vif->ndev, "there is no current Connect Request\n");
-               mutex_unlock(&wilc->deinit_lock);
-               return;
-       }
-
-       msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false);
-       if (IS_ERR(msg)) {
-               mutex_unlock(&wilc->deinit_lock);
-               return;
-       }
-
-       msg->body.mac_info.status = buffer[7];
-       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                  "Received MAC status= %d Reason= %d Info = %d\n",
-                  buffer[7], buffer[8], buffer[9]);
-       result = wilc_enqueue_work(msg);
-       if (result) {
-               PRINT_ER(vif->ndev, "enqueue work failed\n");
-               kfree(msg);
-       }
-
-       mutex_unlock(&wilc->deinit_lock);
-}
-
-void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
-{
-       int result;
-       int id;
-       struct host_if_drv *hif_drv;
-       struct wilc_vif *vif;
-
-       id = get_unaligned_le32(&buffer[length - 4]);
-       vif = wilc_get_vif_from_idx(wilc, id);
-       if (!vif)
-               return;
-       hif_drv = vif->hif_drv;
-       PRINT_INFO(vif->ndev, GENERIC_DBG, "Scan notification received\n");
-
-       if (!hif_drv) {
-               PRINT_ER(vif->ndev, "hif driver is NULL\n");
-               return;
-       }
-
-       if (hif_drv->usr_scan_req.scan_result) {
-               struct host_if_msg *msg;
-
-               msg = wilc_alloc_work(vif, handle_scan_complete, false);
-               if (IS_ERR(msg))
-                       return;
-
-               result = wilc_enqueue_work(msg);
-               if (result) {
-                       PRINT_ER(vif->ndev, "enqueue work failed\n");
-                       kfree(msg);
-               }
-       }
-}
-
-int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie,
-                          u32 duration, u16 chan,
-                          void (*expired)(void *, u64), void *user_arg)
-{
-       struct wilc_remain_ch roc;
-       int result;
-
-       PRINT_INFO(vif->ndev, CFG80211_DBG, "%s called\n", __func__);
-       roc.ch = chan;
-       roc.expired = expired;
-       roc.arg = user_arg;
-       roc.duration = duration;
-       roc.cookie = cookie;
-       result = handle_remain_on_chan(vif, &roc);
-       if (result)
-               PRINT_ER(vif->ndev, "%s: failed to set remain on channel\n",
-                        __func__);
-
-       return result;
-}
-
-int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie)
-{
-       int result;
-       struct host_if_msg *msg;
-       struct host_if_drv *hif_drv = vif->hif_drv;
-
-       if (!hif_drv) {
-               PRINT_ER(vif->ndev, "hif driver is NULL\n");
-               return -EFAULT;
-       }
-
-       del_timer(&hif_drv->remain_on_ch_timer);
-
-       msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
-       if (IS_ERR(msg))
-               return PTR_ERR(msg);
-
-       msg->body.remain_on_ch.cookie = cookie;
-
-       result = wilc_enqueue_work(msg);
-       if (result) {
-               PRINT_ER(vif->ndev, "enqueue work failed\n");
-               kfree(msg);
-       }
-
-       return result;
-}
-
-void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
-{
-       struct wid wid;
-       int result;
-       struct wilc_reg_frame reg_frame;
-
-       wid.id = WID_REGISTER_FRAME;
-       wid.type = WID_STR;
-       wid.size = sizeof(reg_frame);
-       wid.val = (u8 *)&reg_frame;
-
-       memset(&reg_frame, 0x0, sizeof(reg_frame));
-       reg_frame.reg = reg;
-
-       switch (frame_type) {
-       case IEEE80211_STYPE_ACTION:
-               PRINT_INFO(vif->ndev, HOSTINF_DBG, "ACTION\n");
-               reg_frame.reg_id = WILC_FW_ACTION_FRM_IDX;
-               break;
-
-       case IEEE80211_STYPE_PROBE_REQ:
-               PRINT_INFO(vif->ndev, HOSTINF_DBG, "PROBE REQ\n");
-               reg_frame.reg_id = WILC_FW_PROBE_REQ_IDX;
-               break;
-
-       default:
-               PRINT_INFO(vif->ndev, HOSTINF_DBG, "Not valid frame type\n");
-               break;
-       }
-       reg_frame.frame_type = cpu_to_le16(frame_type);
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev, "Failed to frame register\n");
-}
-
-int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
-                   struct cfg80211_beacon_data *params)
-{
-       struct wid wid;
-       int result;
-       u8 *cur_byte;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                  "Setting adding beacon\n");
-
-       wid.id = WID_ADD_BEACON;
-       wid.type = WID_BIN;
-       wid.size = params->head_len + params->tail_len + 16;
-       wid.val = kzalloc(wid.size, GFP_KERNEL);
-       if (!wid.val) {
-               PRINT_ER(vif->ndev, "Failed to allocate buffer\n");
-               return -ENOMEM;
-       }
-
-       cur_byte = wid.val;
-       put_unaligned_le32(interval, cur_byte);
-       cur_byte += 4;
-       put_unaligned_le32(dtim_period, cur_byte);
-       cur_byte += 4;
-       put_unaligned_le32(params->head_len, cur_byte);
-       cur_byte += 4;
-
-       if (params->head_len > 0)
-               memcpy(cur_byte, params->head, params->head_len);
-       cur_byte += params->head_len;
-
-       put_unaligned_le32(params->tail_len, cur_byte);
-       cur_byte += 4;
-
-       if (params->tail_len > 0)
-               memcpy(cur_byte, params->tail, params->tail_len);
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev, "Failed to send add beacon\n");
-
-       kfree(wid.val);
-
-       return result;
-}
-
-int wilc_del_beacon(struct wilc_vif *vif)
-{
-       int result;
-       struct wid wid;
-       u8 del_beacon = 0;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                  "Setting deleting beacon message queue params\n");
-
-       wid.id = WID_DEL_BEACON;
-       wid.type = WID_CHAR;
-       wid.size = sizeof(char);
-       wid.val = &del_beacon;
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev, "Failed to send delete beacon\n");
-
-       return result;
-}
-
-int wilc_add_station(struct wilc_vif *vif, const u8 *mac,
-                    struct station_parameters *params)
-{
-       struct wid wid;
-       int result;
-       u8 *cur_byte;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                  "Setting adding station message queue params\n");
-
-       wid.id = WID_ADD_STA;
-       wid.type = WID_BIN;
-       wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len;
-       wid.val = kmalloc(wid.size, GFP_KERNEL);
-       if (!wid.val)
-               return -ENOMEM;
-
-       cur_byte = wid.val;
-       wilc_hif_pack_sta_param(vif, cur_byte, mac, params);
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result != 0)
-               PRINT_ER(vif->ndev, "Failed to send add station\n");
-
-       kfree(wid.val);
-
-       return result;
-}
-
-int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr)
-{
-       struct wid wid;
-       int result;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                  "Setting deleting station message queue params\n");
-
-       wid.id = WID_REMOVE_STA;
-       wid.type = WID_BIN;
-       wid.size = ETH_ALEN;
-       wid.val = kzalloc(wid.size, GFP_KERNEL);
-       if (!wid.val) {
-               PRINT_ER(vif->ndev, "Failed to allocate buffer\n");
-               return -ENOMEM;
-       }
-
-       if (!mac_addr)
-               eth_broadcast_addr(wid.val);
-       else
-               ether_addr_copy(wid.val, mac_addr);
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev, "Failed to del station\n");
-
-       kfree(wid.val);
-
-       return result;
-}
-
-int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN])
-{
-       struct wid wid;
-       int result;
-       int i;
-       u8 assoc_sta = 0;
-       struct wilc_del_all_sta del_sta;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                  "Setting deauthenticating station message queue params\n");
-       memset(&del_sta, 0x0, sizeof(del_sta));
-       for (i = 0; i < WILC_MAX_NUM_STA; i++) {
-               if (!is_zero_ether_addr(mac_addr[i])) {
-                       PRINT_INFO(vif->ndev,
-                                  CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n",
-                                  mac_addr[i][0], mac_addr[i][1],
-                                  mac_addr[i][2], mac_addr[i][3],
-                                  mac_addr[i][4], mac_addr[i][5]);
-                       assoc_sta++;
-                       ether_addr_copy(del_sta.mac[i], mac_addr[i]);
-               }
-       }
-       if (!assoc_sta) {
-               PRINT_INFO(vif->ndev, CFG80211_DBG, "NO ASSOCIATED STAS\n");
-               return 0;
-       }
-       del_sta.assoc_sta = assoc_sta;
-
-       wid.id = WID_DEL_ALL_STA;
-       wid.type = WID_STR;
-       wid.size = (assoc_sta * ETH_ALEN) + 1;
-       wid.val = (u8 *)&del_sta;
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev, "Failed to send delete all station\n");
-
-       return result;
-}
-
-int wilc_edit_station(struct wilc_vif *vif, const u8 *mac,
-                     struct station_parameters *params)
-{
-       struct wid wid;
-       int result;
-       u8 *cur_byte;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                  "Setting editing station message queue params\n");
-
-       wid.id = WID_EDIT_STA;
-       wid.type = WID_BIN;
-       wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len;
-       wid.val = kmalloc(wid.size, GFP_KERNEL);
-       if (!wid.val)
-               return -ENOMEM;
-
-       cur_byte = wid.val;
-       wilc_hif_pack_sta_param(vif, cur_byte, mac, params);
-
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev, "Failed to send edit station\n");
-
-       kfree(wid.val);
-       return result;
-}
-
-int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
-{
-       struct wid wid;
-       int result;
-       s8 power_mode;
-
-       if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled)
-               return 0;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG, "\n\n>> Setting PS to %d <<\n\n",
-                  enabled);
-       if (enabled)
-               power_mode = WILC_FW_MIN_FAST_PS;
-       else
-               power_mode = WILC_FW_NO_POWERSAVE;
-
-       wid.id = WID_POWER_MANAGEMENT;
-       wid.val = &power_mode;
-       wid.size = sizeof(char);
-       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                     wilc_get_vif_idx(vif));
-       if (result)
-               PRINT_ER(vif->ndev, "Failed to send power management\n");
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-       else
-               store_power_save_current_state(vif, power_mode);
-#endif
-
-       return result;
-}
-
-int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count,
-                               u8 *mc_list)
-{
-       int result;
-       struct host_if_msg *msg;
-
-       PRINT_INFO(vif->ndev, HOSTINF_DBG,
-                  "Setting Multicast Filter params\n");
-       msg = wilc_alloc_work(vif, handle_set_mcast_filter, false);
-       if (IS_ERR(msg))
-               return PTR_ERR(msg);
-
-       msg->body.mc_info.enabled = enabled;
-       msg->body.mc_info.cnt = count;
-       msg->body.mc_info.mc_list = mc_list;
-
-       result = wilc_enqueue_work(msg);
-       if (result) {
-               PRINT_ER(vif->ndev, "enqueue work failed\n");
-               kfree(msg);
-       }
-       return result;
-}
-
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-void handle_powersave_state_changes(struct work_struct *work)
-{
-       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-       struct wilc_vif *vif = msg->vif;
-
-       PRINT_INFO(vif->ndev, GENERIC_DBG, "Recover PS = %d\n",
-                  vif->pwrsave_current_state);
-
-       /* Recover PS previous state */
-       wilc_set_power_mgmt(vif, vif->pwrsave_current_state, 0);
-}
-
-void wilc_powersave_state_changes(struct wilc_vif *vif)
-{
-       int result;
-       struct host_if_msg *msg;
-
-       msg = wilc_alloc_work(vif, handle_powersave_state_changes, false);
-       if (IS_ERR(msg))
-               return;
-
-       result = wilc_enqueue_work(msg);
-       if (result) {
-               PRINT_ER(vif->ndev, "enqueue work failed\n");
-               kfree(msg);
-       }
-}
-#endif
-
-int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
-{
-       struct wid wid;
-
-       wid.id = WID_TX_POWER;
-       wid.type = WID_CHAR;
-       wid.val = &tx_power;
-       wid.size = sizeof(char);
-
-       return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                  wilc_get_vif_idx(vif));
-}
-
-int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
-{
-       struct wid wid;
-
-       wid.id = WID_TX_POWER;
-       wid.type = WID_CHAR;
-       wid.val = tx_power;
-       wid.size = sizeof(char);
-
-       return wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1,
-                                   wilc_get_vif_idx(vif));
-}
-
-bool is_valid_gpio(struct wilc_vif *vif, u8 gpio)
-{
-       switch (vif->wilc->chip) {
-       case WILC_1000:
-               if (gpio == 0 || gpio == 1 || gpio == 4 || gpio == 6)
-                       return true;
-               else
-                       return false;
-       case WILC_3000:
-               if (gpio == 0 || gpio == 3 || gpio == 4 ||
-                   (gpio >= 17 && gpio <= 20))
-                       return true;
-               else
-                       return false;
-       default:
-               return false;
-       }
-}
-
-int wilc_set_antenna(struct wilc_vif *vif, u8 mode)
-{
-       struct wid wid;
-       int ret;
-       struct sysfs_attr_group *attr_syfs_p = &vif->attr_sysfs;
-       struct host_if_set_ant set_ant;
-
-       set_ant.mode = mode;
-
-       if (attr_syfs_p->ant_swtch_mode == ANT_SWTCH_INVALID_GPIO_CTRL) {
-               PRINT_ER(vif->ndev, "Ant switch GPIO mode is invalid.\n");
-               PRINT_ER(vif->ndev, "Set it using /sys/wilc/ant_swtch_mode\n");
-               return WILC_FAIL;
-       }
-
-       if (is_valid_gpio(vif, attr_syfs_p->antenna1)) {
-               set_ant.antenna1 = attr_syfs_p->antenna1;
-       } else {
-               PRINT_ER(vif->ndev, "Invalid GPIO%d\n", attr_syfs_p->antenna1);
-               return WILC_FAIL;
-       }
-
-       if (attr_syfs_p->ant_swtch_mode == ANT_SWTCH_DUAL_GPIO_CTRL) {
-               if ((attr_syfs_p->antenna2 != attr_syfs_p->antenna1) &&
-                   is_valid_gpio(vif, attr_syfs_p->antenna2)) {
-                       set_ant.antenna2 = attr_syfs_p->antenna2;
-               } else {
-                       PRINT_ER(vif->ndev, "Invalid GPIO %d\n",
-                                attr_syfs_p->antenna2);
-                       return WILC_FAIL;
-               }
-       }
-
-       set_ant.gpio_mode = attr_syfs_p->ant_swtch_mode;
-
-       wid.id = WID_ANTENNA_SELECTION;
-       wid.type = WID_BIN;
-       wid.val = (u8 *)&set_ant;
-       wid.size = sizeof(struct host_if_set_ant);
-       if (attr_syfs_p->ant_swtch_mode == ANT_SWTCH_SNGL_GPIO_CTRL)
-               PRINT_INFO(vif->ndev, CFG80211_DBG,
-                          "set antenna %d on GPIO %d\n", set_ant.mode,
-                          set_ant.antenna1);
-       else if (attr_syfs_p->ant_swtch_mode == ANT_SWTCH_DUAL_GPIO_CTRL)
-               PRINT_INFO(vif->ndev, CFG80211_DBG,
-                          "set antenna %d on GPIOs %d and %d\n",
-                          set_ant.mode, set_ant.antenna1,
-                          set_ant.antenna2);
-
-       ret = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
-                                  wilc_get_vif_idx(vif));
-       if (ret)
-               PRINT_ER(vif->ndev, "Failed to set antenna mode\n");
-
-       return ret;
-}
diff --git a/drivers/net/wireless/mchp/host_interface.h b/drivers/net/wireless/mchp/host_interface.h
deleted file mode 100644 (file)
index 92c1c17..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
- * All rights reserved.
- */
-
-#ifndef HOST_INT_H
-#define HOST_INT_H
-#include <linux/ieee80211.h>
-#include "wilc_wlan_if.h"
-
-enum {
-       WILC_IDLE_MODE = 0x0,
-       WILC_AP_MODE = 0x1,
-       WILC_STATION_MODE = 0x2,
-       WILC_GO_MODE = 0x3,
-       WILC_CLIENT_MODE = 0x4,
-       WILC_MONITOR_MODE = 0x5
-};
-
-enum {
-       WILC_P2P_IFC = 0x00,
-       WILC_WLAN_IFC = 0x01,
-};
-
-#define IFC_0 "wlan0"
-#define IFC_1 "p2p0"
-
-#define WILC_MAX_NUM_STA                       9
-#define WILC_MAX_NUM_SCANNED_CH                        14
-#define WILC_MAX_NUM_PROBED_SSID               10
-
-#define WILC_TX_MIC_KEY_LEN                    8
-#define WILC_RX_MIC_KEY_LEN                    8
-
-#define WILC_MAX_NUM_PMKIDS                    16
-#define WILC_ADD_STA_LENGTH                    40
-#define WILC_NUM_CONCURRENT_IFC                        2
-
-enum {
-       WILC_SET_CFG = 0,
-       WILC_GET_CFG
-};
-
-#define WILC_MAX_ASSOC_RESP_FRAME_SIZE   256
-extern uint32_t cfg_packet_timeout;
-
-struct assoc_resp {
-       __le16 capab_info;
-       __le16 status_code;
-       __le16 aid;
-} __packed;
-
-struct rf_info {
-       u8 link_speed;
-       s8 rssi;
-       u32 tx_cnt;
-       u32 rx_cnt;
-       u32 tx_fail_cnt;
-};
-
-enum host_if_state {
-       HOST_IF_IDLE                    = 0,
-       HOST_IF_SCANNING                = 1,
-       HOST_IF_CONNECTING              = 2,
-       HOST_IF_WAITING_CONN_RESP       = 3,
-       HOST_IF_CONNECTED               = 4,
-       HOST_IF_P2P_LISTEN              = 5,
-       HOST_IF_FORCE_32BIT             = 0xFFFFFFFF
-};
-
-struct wilc_pmkid {
-       u8 bssid[ETH_ALEN];
-       u8 pmkid[WLAN_PMKID_LEN];
-} __packed;
-
-struct wilc_pmkid_attr {
-       u8 numpmkid;
-       struct wilc_pmkid pmkidlist[WILC_MAX_NUM_PMKIDS];
-} __packed;
-
-struct cfg_param_attr {
-       u32 flag;
-       u16 short_retry_limit;
-       u16 long_retry_limit;
-       u16 frag_threshold;
-       u16 rts_threshold;
-};
-
-enum cfg_param {
-       WILC_CFG_PARAM_RETRY_SHORT = BIT(0),
-       WILC_CFG_PARAM_RETRY_LONG = BIT(1),
-       WILC_CFG_PARAM_FRAG_THRESHOLD = BIT(2),
-       WILC_CFG_PARAM_RTS_THRESHOLD = BIT(3)
-};
-
-enum scan_event {
-       SCAN_EVENT_NETWORK_FOUND        = 0,
-       SCAN_EVENT_DONE                 = 1,
-       SCAN_EVENT_ABORTED              = 2,
-       SCAN_EVENT_FORCE_32BIT          = 0xFFFFFFFF
-};
-
-enum conn_event {
-       EVENT_CONN_RESP         = 0,
-       EVENT_DISCONN_NOTIF     = 1,
-       EVENT_FORCE_32BIT               = 0xFFFFFFFF
-};
-
-enum {
-       WILC_HIF_SDIO = 0,
-       WILC_HIF_SPI = BIT(0),
-       WILC_HIF_SDIO_GPIO_IRQ = BIT(1)
-};
-
-enum {
-       WILC_MAC_STATUS_INIT = -1,
-       WILC_MAC_STATUS_DISCONNECTED = 0,
-       WILC_MAC_STATUS_CONNECTED = 1
-};
-
-struct wilc_rcvd_net_info {
-       s8 rssi;
-       u8 ch;
-       u16 frame_len;
-       struct ieee80211_mgmt *mgmt;
-};
-
-typedef void (*wilc_remain_on_chan_ready)(void *);
-
-struct wilc_user_scan_req {
-       void (*scan_result)(enum scan_event evt,
-                           struct wilc_rcvd_net_info *info, void *priv);
-       void *arg;
-       u32 ch_cnt;
-};
-
-struct wilc_conn_info {
-       u8 bssid[ETH_ALEN];
-       u8 security;
-       enum authtype auth_type;
-       u8 ch;
-       u8 *req_ies;
-       size_t req_ies_len;
-       u8 *resp_ies;
-       u16 resp_ies_len;
-       u16 status;
-       void (*conn_result)(enum conn_event evt, u8 status, void *priv);
-       void *arg;
-       void *param;
-};
-
-struct wilc_remain_ch {
-       u16 ch;
-       u32 duration;
-       void (*expired)(void *priv, u64 cookie);
-       void *arg;
-       u64 cookie;
-};
-
-struct host_if_drv {
-       struct wilc_user_scan_req usr_scan_req;
-       struct wilc_conn_info conn_info;
-       struct wilc_remain_ch remain_on_ch;
-       u64 p2p_timeout;
-
-       enum host_if_state hif_state;
-
-       u8 assoc_bssid[ETH_ALEN];
-       struct completion comp_test_key_block;
-       struct completion comp_test_disconn_block;
-       struct completion comp_get_rssi;
-       struct completion comp_inactive_time;
-
-       struct timer_list scan_timer;
-       struct wilc_vif *scan_timer_vif;
-
-       struct timer_list connect_timer;
-       struct wilc_vif *connect_timer_vif;
-
-       struct timer_list remain_on_ch_timer;
-       struct wilc_vif *remain_on_ch_timer_vif;
-
-       bool ifc_up;
-       int driver_handler_id;
-       u8 assoc_resp[WILC_MAX_ASSOC_RESP_FRAME_SIZE];
-};
-
-struct wilc_vif;
-
-signed int wilc_send_buffered_eap(struct wilc_vif *vif,
-                                 void (*deliver_to_stack)(struct wilc_vif *,
-                                                          u8 *, u32, u32, u8),
-                                 void (*eap_buf_param)(void *), u8 *buff,
-                                 unsigned int size, unsigned int pkt_offset,
-                                 void *user_arg);
-int wilc_remove_wep_key(struct wilc_vif *vif, u8 index);
-int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index);
-int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
-                            u8 index);
-int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
-                           u8 index, u8 mode, enum authtype auth_type);
-int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
-                const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
-                u8 mode, u8 cipher_mode, u8 index);
-s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac,
-                          u32 *out_val);
-int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
-                   u8 index, u32 key_rsc_len, const u8 *key_rsc,
-                   const u8 *rx_mic, const u8 *tx_mic, u8 mode,
-                   u8 cipher_mode);
-int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid);
-int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr);
-int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr);
-int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
-                     size_t ies_len);
-int wilc_disconnect(struct wilc_vif *vif);
-int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel);
-int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level);
-int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
-             u8 *ch_freq_list, u8 ch_list_len,
-             void (*scan_result_fn)(enum scan_event,
-                                    struct wilc_rcvd_net_info *, void *),
-             void *user_arg, struct cfg80211_scan_request *request);
-int wilc_hif_set_cfg(struct wilc_vif *vif,
-                    struct cfg_param_attr *cfg_param);
-int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler);
-int wilc_deinit(struct wilc_vif *vif);
-int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
-                   struct cfg80211_beacon_data *params);
-int wilc_del_beacon(struct wilc_vif *vif);
-int wilc_add_station(struct wilc_vif *vif, const u8 *mac,
-                    struct station_parameters *params);
-int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]);
-int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr);
-int wilc_edit_station(struct wilc_vif *vif, const u8 *mac,
-                     struct station_parameters *params);
-int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout);
-int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count,
-                               u8 *mc_list);
-int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie,
-                          u32 duration, u16 chan,
-                          void (*expired)(void *, u64), void *user_arg);
-int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie);
-void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg);
-int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
-                            u8 ifc_id);
-int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode);
-int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats);
-void wilc_resolve_disconnect_aberration(struct wilc_vif *vif);
-int wilc_get_vif_idx(struct wilc_vif *vif);
-int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power);
-int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power);
-/*0 select antenna 1 , 2 select antenna mode , 2 allow the firmware to choose
- * the best antenna
- */
-int wilc_set_antenna(struct wilc_vif *vif, u8 mode);
-
-void wilc_set_wowlan_trigger(struct wilc_vif *vif, u8 wowlan_trigger);
-
-extern u8 wilc_initialized;
-s32 handle_scan_done(struct wilc_vif *vif, enum scan_event evt);
-void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length);
-void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length);
-void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length);
-void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
-                               struct cfg80211_crypto_settings *crypto);
-void wilc_powersave_state_changes(struct wilc_vif *vif);
-#endif
diff --git a/drivers/net/wireless/mchp/microchip,wilc,sdio.txt b/drivers/net/wireless/mchp/microchip,wilc,sdio.txt
deleted file mode 100644 (file)
index 028c640..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-* Microchip WILC wireless SDIO device
-
-The wilc1000 chips can be connected via SDIO. The node is used to specifiy
-child node to the SDIO controller that connects the device to the system.
-
-Required properties:
-- compatible   :       Should be "microchip,wilc1000-sdio"
-- irq-gpios    :       Connect to a host IRQ
-- reset-gpios  :       Reset module GPIO
-- chip_en-gpios        :       Chip enable GPIO
-- reg          :       Slot ID used in the controller
-
-Optional:
-- bus-width    :       Number of data lines wired up the slot. Default 1 bit.
-
-
-Examples:
-mmc1: mmc@fc000000 {
-               pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_mmc1_clk_cmd_dat0 &pinctrl_mmc1_dat1_3>;
-               non-removable;
-               vmmc-supply = <&vcc_mmc1_reg>;
-               vqmmc-supply = <&vcc_3v3_reg>;
-               status = "okay";
-
-               wilc_sdio@0 {
-                       compatible = "microchip,wilc1000", "microchip,wilc3000";
-                       irq-gpios = <&pioC 27 0>;
-                       reset-gpios = <&pioB 28 0>;
-                       chip_en-gpios = <&pioC 30 0>;
-                       status = "okay";
-                       reg = <0>;
-                       bus-width = <4>;
-               }
-       };
-}
diff --git a/drivers/net/wireless/mchp/microchip,wilc,spi.txt b/drivers/net/wireless/mchp/microchip,wilc,spi.txt
deleted file mode 100644 (file)
index 2e2a930..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-* Microchip WILC wireless SPI device
-
-The wilc1000 chips can be connected via SPI. This document describes
-the binding for the SPI connected module.
-
-Required properties:
-- compatible           : Should be "microchip,wilc1000-spi"
-- spi-max-frequency    : Maximum SPI clocking speed of device in Hz
-- reg                  : Chip select address of device
-- irq-gpios            : Connect to a host IRQ
-- reset-gpios          : Reset module GPIO
-- chip_en-gpios:       : Chip enable GPIO
-
-
-Examples:
-
-spi1: spi@fc018000 {
-               cs-gpios = <&pioB 21 0>;
-               status = "okay";
-
-               wilc_spi@0 {
-                       compatible = "microchip,wilc1000", "microchip,wilc3000";
-                       spi-max-frequency = <48000000>;
-                       reg = <0>;
-                       irq-gpios = <&pioC 27 0>;
-                       reset-gpios = <&pioB 28 0>;
-                       chip_en-gpios = <&pioC 30 0>;
-                       status = "okay";
-               };
-};
diff --git a/drivers/net/wireless/mchp/microchip,wilc1000,sdio.txt b/drivers/net/wireless/mchp/microchip,wilc1000,sdio.txt
new file mode 100644 (file)
index 0000000..8dc88bc
--- /dev/null
@@ -0,0 +1,42 @@
+* Microchip WILC wireless SDIO device
+
+The wilc1000 chips can be connected via SDIO. The node is used to specifiy
+child node to the SDIO controller that connects the device to the system.
+
+Required properties:
+- compatible   :       Should be "microchip,wilc1000-sdio"
+- irq-gpios    :       Connect to a host IRQ
+- reset-gpios  :       Reset module GPIO
+- chip_en-gpios        :       Chip enable GPIO
+- reg          :       Slot ID used in the controller
+
+Optional:
+- bus-width    :       Number of data lines wired up the slot. Default 1 bit.
+- rtc_clk      :       Clock connected on the rtc clock line. Must be assigned
+                       a frequency with assigned-clocks property, and must be
+                       connected to a clock provider.
+
+Examples:
+mmc1: mmc@fc000000 {
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_mmc1_clk_cmd_dat0 &pinctrl_mmc1_dat1_3>;
+               non-removable;
+               vmmc-supply = <&vcc_mmc1_reg>;
+               vqmmc-supply = <&vcc_3v3_reg>;
+               status = "okay";
+
+               wilc_sdio@0 {
+                       compatible = "microchip,wilc1000", "microchip,wilc3000";
+                       irq-gpios = <&pioC 27 0>;
+                       reset-gpios = <&pioB 28 0>;
+                       chip_en-gpios = <&pioC 30 0>;
+                       clocks = <&pck1>;
+                       clock-names = "rtc_clk";
+                       assigned-clocks = <&pck1>;
+                       assigned-clock-rates = <32768>;
+                       status = "okay";
+                       reg = <0>;
+                       bus-width = <4>;
+               }
+       };
+}
diff --git a/drivers/net/wireless/mchp/microchip,wilc1000,spi.txt b/drivers/net/wireless/mchp/microchip,wilc1000,spi.txt
new file mode 100644 (file)
index 0000000..dfc01f4
--- /dev/null
@@ -0,0 +1,38 @@
+* Microchip WILC wireless SPI device
+
+The wilc1000 chips can be connected via SPI. This document describes
+the binding for the SPI connected module.
+
+Required properties:
+- compatible           : Should be "microchip,wilc1000-spi"
+- spi-max-frequency    : Maximum SPI clocking speed of device in Hz
+- reg                  : Chip select address of device
+- irq-gpios            : Connect to a host IRQ
+- reset-gpios          : Reset module GPIO
+- chip_en-gpios:       : Chip enable GPIO
+
+Optional:
+- rtc_clk      :       Clock connected on the rtc clock line. Must be assigned
+                       a frequency with assigned-clocks property, and must be
+                       connected to a clock provider.
+
+Examples:
+
+spi1: spi@fc018000 {
+               cs-gpios = <&pioB 21 0>;
+               status = "okay";
+
+               wilc_spi@0 {
+                       compatible = "microchip,wilc1000", "microchip,wilc3000";
+                       spi-max-frequency = <48000000>;
+                       reg = <0>;
+                       irq-gpios = <&pioC 27 0>;
+                       reset-gpios = <&pioB 28 0>;
+                       chip_en-gpios = <&pioC 30 0>;
+                       clocks = <&pck1>;
+                       clock-names = "rtc_clk";
+                       assigned-clocks = <&pck1>;
+                       assigned-clock-rates = <32768>;
+                       status = "okay";
+               };
+};
index 8d32e53..3c4a871 100644 (file)
@@ -9,7 +9,7 @@
 
 static struct kobject *wilc_kobj;
 static int device_created;
-static struct wilc_vif *vif[WILC_NUM_CONCURRENT_IFC];
+static struct wilc *wl;
 
 static ssize_t wilc_sysfs_show(struct kobject *kobj,
                               struct kobj_attribute *attr, char *buf)
@@ -17,13 +17,13 @@ static ssize_t wilc_sysfs_show(struct kobject *kobj,
        int attr_val = -1;
 
        if (strcmp(attr->attr.name, "p2p_mode") == 0)
-               attr_val = vif[0]->attr_sysfs.p2p_mode;
+               attr_val = wl->attr_sysfs.p2p_mode;
        if (strcmp(attr->attr.name, "ant_swtch_mode") == 0)
-               attr_val = vif[0]->attr_sysfs.ant_swtch_mode;
+               attr_val = wl->attr_sysfs.ant_swtch_mode;
        else if (strcmp(attr->attr.name, "antenna1") == 0)
-               attr_val = vif[0]->attr_sysfs.antenna1;
+               attr_val = wl->attr_sysfs.antenna1;
        else if (strcmp(attr->attr.name, "antenna2") == 0)
-               attr_val = vif[0]->attr_sysfs.antenna2;
+               attr_val = wl->attr_sysfs.antenna2;
 
        return sprintf(buf, "%d\n", attr_val);
 }
@@ -33,25 +33,20 @@ static ssize_t wilc_sysfs_store(struct kobject *kobj,
                                size_t count)
 {
        int attr_val;
-       int i;
-
-       for (i = 0; i < WILC_NUM_CONCURRENT_IFC; i++) {
-               if (kstrtoint(buf, 10, &attr_val))
-                       PRINT_ER(vif[i]->ndev,
-                                "Failed to convert p2p_mode string");
-               if (strcmp(attr->attr.name, "p2p_mode") == 0) {
-                       vif[i]->attr_sysfs.p2p_mode = (attr_val?1:0);
-               } else if (strcmp(attr->attr.name, "ant_swtch_mode") == 0) {
-                       if (attr_val > ANT_SWTCH_DUAL_GPIO_CTRL)
-                               PRINT_ER(vif[i]->ndev,
-                                        "Valid antenna switch modes:\n1-Single Antenna, 2-Dual Antenna\n");
-                       else
-                               vif[i]->attr_sysfs.ant_swtch_mode = attr_val;
-               } else if (strcmp(attr->attr.name, "antenna1") == 0) {
-                       vif[i]->attr_sysfs.antenna1 = attr_val;
-               } else if (strcmp(attr->attr.name, "antenna2") == 0) {
-                       vif[i]->attr_sysfs.antenna2 = attr_val;
-               }
+
+       if (kstrtoint(buf, 10, &attr_val))
+               pr_err("Failed to convert p2p_mode string");
+       if (strcmp(attr->attr.name, "p2p_mode") == 0) {
+               wl->attr_sysfs.p2p_mode = (attr_val?1:0);
+       } else if (strcmp(attr->attr.name, "ant_swtch_mode") == 0) {
+               if (attr_val > ANT_SWTCH_DUAL_GPIO_CTRL)
+                       pr_err("Valid antenna switch modes:\n1-Single Antenna, 2-Dual Antenna\n");
+               else
+                       wl->attr_sysfs.ant_swtch_mode = attr_val;
+       } else if (strcmp(attr->attr.name, "antenna1") == 0) {
+               wl->attr_sysfs.antenna1 = attr_val;
+       } else if (strcmp(attr->attr.name, "antenna2") == 0) {
+               wl->attr_sysfs.antenna2 = attr_val;
        }
 
        return count;
@@ -82,13 +77,9 @@ static struct attribute_group attr_group = {
        .attrs = wilc_attrs,
 };
 
-void wilc_sysfs_init(struct wilc_vif *vif1, struct wilc_vif *vif2)
+void wilc_sysfs_init(struct wilc *wilc)
 {
        int retval;
-       int i;
-
-       vif[0] = vif1;
-       vif[1] = vif2;
 
        if (device_created)
                return;
@@ -99,15 +90,14 @@ void wilc_sysfs_init(struct wilc_vif *vif1, struct wilc_vif *vif2)
                return;
        }
 
-       for (i = 0; i < WILC_NUM_CONCURRENT_IFC; i++) {
-               /* By default p2p mode is Group Owner */
-               vif[i]->attr_sysfs.p2p_mode = 1;
-               vif[i]->attr_sysfs.ant_swtch_mode = ANT_SWTCH_INVALID_GPIO_CTRL;
-               vif[i]->attr_sysfs.antenna1 = 0xFF;
-               vif[i]->attr_sysfs.antenna2 = 0xFF;
-       }
        retval = sysfs_create_group(wilc_kobj, &attr_group);
        device_created = 1;
+       wl = wilc;
+       /* By default p2p mode is Group Owner */
+       wl->attr_sysfs.p2p_mode = 1;
+       wl->attr_sysfs.ant_swtch_mode = ANT_SWTCH_INVALID_GPIO_CTRL;
+       wl->attr_sysfs.antenna1 = 0xFF;
+       wl->attr_sysfs.antenna2 = 0xFF;
 }
 
 void wilc_sysfs_exit(void)
@@ -116,4 +106,3 @@ void wilc_sysfs_exit(void)
        sysfs_remove_group(wilc_kobj, &attr_group);
        kobject_put(wilc_kobj);
 }
-
index a92a34b..6364331 100644 (file)
@@ -74,7 +74,7 @@ static const struct cmd_entry cmd_table[] = {
 
 static int wilc_bt_dev_open(struct inode *i, struct file *f)
 {
-       pr_err("at_pwr_dev: open()\n");
+       pr_info("at_pwr_dev: open()\n");
        return 0;
 }
 
@@ -210,9 +210,9 @@ static void handle_cmd_cca_thrshld(char *param)
 int wilc_bt_power_down(struct wilc *wilc, int source)
 {
        const struct wilc_hif_func *hif_func = wilc->hif_func;
+       int ret;
 
        if (source == DEV_BT) {
-               int ret;
                u32 reg;
 
                pr_info("AT PWR: bt_power_down\n");
@@ -322,7 +322,11 @@ int wilc_bt_power_down(struct wilc *wilc, int source)
                pr_warn("Another device is preventing power down. request source is %s\n",
                        (source == DEV_WIFI ? "Wifi" : "BT"));
        } else {
-               wilc_wlan_power_off_sequence(wilc);
+               ret = wilc_wlan_power_off_sequence(wilc);
+               if (ret) {
+                       mutex_unlock(&wilc->cs);
+                       return ret;
+               }
        }
        wilc->power_status[source] = false;
 
diff --git a/drivers/net/wireless/mchp/wilc_hif.c b/drivers/net/wireless/mchp/wilc_hif.c
new file mode 100644 (file)
index 0000000..bd36d40
--- /dev/null
@@ -0,0 +1,2612 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
+ * All rights reserved.
+ */
+
+#include <linux/etherdevice.h>
+
+#include "wilc_wfi_netdevice.h"
+#include "wilc_netdev.h"
+#include "wilc_wfi_cfgoperations.h"
+
+#define WILC_HIF_SCAN_TIMEOUT_MS                    5000
+#define WILC_HIF_CONNECT_TIMEOUT_MS                 9500
+
+#define WILC_FALSE_FRMWR_CHANNEL                   100
+#define WILC_MAX_RATES_SUPPORTED                   12
+
+/* Generic success will return 0 */
+#define WILC_SUCCESS           0       /* Generic success */
+
+/* Negative numbers to indicate failures */
+/* Generic Fail */
+#define        WILC_FAIL               -100
+/* Busy with another operation*/
+#define        WILC_BUSY               -101
+/* A given argument is invalid*/
+#define        WILC_INVALID_ARGUMENT   -102
+/* An API request would violate the Driver state machine
+ * (i.e. to start PID while not camped)
+ */
+#define        WILC_INVALID_STATE      -103
+/* In copy operations if the copied data is larger than the allocated buffer*/
+#define        WILC_BUFFER_OVERFLOW    -104
+/* null pointer is passed or used */
+#define WILC_NULL_PTR          -105
+#define        WILC_EMPTY              -107
+#define WILC_FULL              -108
+#define        WILC_TIMEOUT            -109
+/* The required operation have been canceled by the user*/
+#define WILC_CANCELED          -110
+/* The Loaded file is corruped or having an invalid format */
+#define WILC_INVALID_FILE      -112
+/* Cant find the file to load */
+#define WILC_NOT_FOUND         -113
+#define WILC_NO_MEM            -114
+#define WILC_UNSUPPORTED_VERSION -115
+#define WILC_FILE_EOF          -116
+
+#if KERNEL_VERSION(3, 17, 0) > LINUX_VERSION_CODE
+struct ieee80211_wmm_ac_param {
+       u8 aci_aifsn; /* AIFSN, ACM, ACI */
+       u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */
+       __le16 txop_limit;
+} __packed;
+
+struct ieee80211_wmm_param_ie {
+       u8 element_id; /* Element ID: 221 (0xdd); */
+       u8 len; /* Length: 24 */
+       u8 oui[3]; /* 00:50:f2 */
+       u8 oui_type; /* 2 */
+       u8 oui_subtype; /* 1 */
+       u8 version; /* 1 for WMM version 1.0 */
+       u8 qos_info; /* AP/STA specific QoS info */
+       u8 reserved; /* 0 */
+       /* AC_BE, AC_BK, AC_VI, AC_VO */
+       struct ieee80211_wmm_ac_param ac[4];
+} __packed;
+#endif
+
+struct send_buffered_eap {
+       void (*deliver_to_stack)(struct wilc_vif *vif, u8 *buff, u32 size,
+                             u32 pkt_offset, u8 status);
+       void (*eap_buf_param)(void *priv);
+       u8 *buff;
+       unsigned int size;
+       unsigned int pkt_offset;
+       void *user_arg;
+};
+
+struct wilc_rcvd_mac_info {
+       u8 status;
+};
+
+struct wilc_set_multicast {
+       u32 enabled;
+       u32 cnt;
+       u8 *mc_list;
+};
+
+struct host_if_wowlan_trigger {
+       u8 wowlan_trigger;
+};
+
+struct bt_coex_mode {
+       u8 bt_coex;
+};
+
+struct host_if_set_ant {
+       u8 mode;
+       u8 antenna1;
+       u8 antenna2;
+       u8 gpio_mode;
+};
+
+struct wilc_del_all_sta {
+       u8 assoc_sta;
+       u8 mac[WILC_MAX_NUM_STA][ETH_ALEN];
+};
+
+struct wilc_op_mode {
+       __le32 mode;
+};
+
+struct wilc_reg_frame {
+       bool reg;
+       u8 reg_id;
+       __le16 frame_type;
+} __packed;
+
+struct wilc_drv_handler {
+       __le32 handler;
+       u8 mode;
+} __packed;
+
+struct wilc_wep_key {
+       u8 index;
+       u8 key_len;
+       u8 key[0];
+} __packed;
+
+struct wilc_sta_wpa_ptk {
+       u8 mac_addr[ETH_ALEN];
+       u8 key_len;
+       u8 key[0];
+} __packed;
+
+struct wilc_ap_wpa_ptk {
+       u8 mac_addr[ETH_ALEN];
+       u8 index;
+       u8 key_len;
+       u8 key[0];
+} __packed;
+
+struct wilc_gtk_key {
+       u8 mac_addr[ETH_ALEN];
+       u8 rsc[8];
+       u8 index;
+       u8 key_len;
+       u8 key[0];
+} __packed;
+
+union wilc_message_body {
+       struct wilc_rcvd_net_info net_info;
+       struct wilc_rcvd_mac_info mac_info;
+       struct wilc_set_multicast mc_info;
+       struct wilc_remain_ch remain_on_ch;
+       char *data;
+       struct send_buffered_eap send_buff_eap;
+       struct host_if_set_ant set_ant;
+       struct host_if_wowlan_trigger wow_trigger;
+       struct bt_coex_mode bt_coex_mode;
+};
+
+struct host_if_msg {
+       union wilc_message_body body;
+       struct wilc_vif *vif;
+       struct work_struct work;
+       void (*fn)(struct work_struct *ws);
+       struct completion work_comp;
+       bool is_sync;
+};
+
+struct wilc_noa_opp_enable {
+       u8 ct_window;
+       u8 cnt;
+       __le32 duration;
+       __le32 interval;
+       __le32 start_time;
+} __packed;
+
+struct wilc_noa_opp_disable {
+       u8 cnt;
+       __le32 duration;
+       __le32 interval;
+       __le32 start_time;
+} __packed;
+
+struct wilc_join_bss_param {
+       char ssid[IEEE80211_MAX_SSID_LEN];
+       u8 ssid_terminator;
+       u8 bss_type;
+       u8 ch;
+       __le16 cap_info;
+       u8 sa[ETH_ALEN];
+       u8 bssid[ETH_ALEN];
+       __le16 beacon_period;
+       u8 dtim_period;
+       u8 supp_rates[WILC_MAX_RATES_SUPPORTED + 1];
+       u8 wmm_cap;
+       u8 uapsd_cap;
+       u8 ht_capable;
+       u8 rsn_found;
+       u8 rsn_grp_policy;
+       u8 mode_802_11i;
+       u8 p_suites[3];
+       u8 akm_suites[3];
+       u8 rsn_cap[2];
+       u8 noa_enabled;
+       __le32 tsf_lo;
+       u8 idx;
+       u8 opp_enabled;
+       union {
+               struct wilc_noa_opp_disable opp_dis;
+               struct wilc_noa_opp_enable opp_en;
+       };
+} __packed;
+
+/* 'msg' should be free by the caller for syc */
+static struct host_if_msg*
+wilc_alloc_work(struct wilc_vif *vif, void (*work_fun)(struct work_struct *),
+               bool is_sync)
+{
+       struct host_if_msg *msg;
+
+       if (!work_fun)
+               return ERR_PTR(-EINVAL);
+
+       msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
+       if (!msg)
+               return ERR_PTR(-ENOMEM);
+       msg->fn = work_fun;
+       msg->vif = vif;
+       msg->is_sync = is_sync;
+       if (is_sync)
+               init_completion(&msg->work_comp);
+
+       return msg;
+}
+
+static int wilc_enqueue_work(struct host_if_msg *msg)
+{
+       INIT_WORK(&msg->work, msg->fn);
+
+       if (!msg->vif || !msg->vif->wilc || !msg->vif->wilc->hif_workqueue)
+               return -EINVAL;
+
+       if (!queue_work(msg->vif->wilc->hif_workqueue, &msg->work))
+               return -EINVAL;
+
+       return 0;
+}
+
+/* The idx starts from 0 to (NUM_CONCURRENT_IFC - 1), but 0 index used as
+ * special purpose in wilc device, so we add 1 to the index to starts from 1.
+ * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC.
+ */
+int wilc_get_vif_idx(struct wilc_vif *vif)
+{
+       return vif->idx + 1;
+}
+
+/* We need to minus 1 from idx which is from wilc device to get real index
+ * of wilc->vif[], because we add 1 when pass to wilc device in the function
+ * wilc_get_vif_idx.
+ * As a result, the index should be between 0 and (NUM_CONCURRENT_IFC - 1).
+ */
+static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx)
+{
+       int index = idx - 1;
+       struct wilc_vif *vif;
+
+       if (index < 0 || index >= WILC_NUM_CONCURRENT_IFC)
+               return NULL;
+
+       list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
+               if (vif->idx == index)
+                       return vif;
+       }
+
+       return NULL;
+}
+
+static void handle_send_buffered_eap(struct work_struct *work)
+{
+       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
+       struct wilc_vif *vif = msg->vif;
+       struct send_buffered_eap *hif_buff_eap = &msg->body.send_buff_eap;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Sending bufferd eapol to WPAS\n");
+       if (!hif_buff_eap->buff)
+               goto out;
+
+       if (hif_buff_eap->deliver_to_stack)
+               hif_buff_eap->deliver_to_stack(vif, hif_buff_eap->buff,
+                                              hif_buff_eap->size,
+                                              hif_buff_eap->pkt_offset,
+                                              PKT_STATUS_BUFFERED);
+       if (hif_buff_eap->eap_buf_param)
+               hif_buff_eap->eap_buf_param(hif_buff_eap->user_arg);
+
+       if (hif_buff_eap->buff != NULL) {
+               kfree(hif_buff_eap->buff);
+               hif_buff_eap->buff = NULL;
+       }
+
+out:
+       kfree(msg);
+}
+
+int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
+             u8 *ch_freq_list, u8 ch_list_len,
+             void (*scan_result_fn)(enum scan_event,
+                                    struct wilc_rcvd_net_info *, void *),
+             void *user_arg, struct cfg80211_scan_request *request)
+{
+       int result = 0;
+       struct wid wid_list[5];
+       u32 index = 0;
+       u32 i, scan_timeout;
+       u8 *buffer;
+       u8 valuesize = 0;
+       u8 *search_ssid_vals = NULL;
+       struct host_if_drv *hif_drv = vif->hif_drv;
+       struct wilc_vif *vif_tmp;
+       int srcu_idx;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Setting SCAN params\n");
+       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Scanning: In [%d] state\n",
+                  hif_drv->hif_state);
+
+       srcu_idx = srcu_read_lock(&vif->wilc->srcu);
+       list_for_each_entry_rcu(vif_tmp, &vif->wilc->vif_list, list) {
+               struct host_if_drv *hif_drv_tmp;
+
+               if (vif_tmp == NULL || vif_tmp->hif_drv == NULL)
+                       continue;
+
+               hif_drv_tmp = vif_tmp->hif_drv;
+
+               if (hif_drv_tmp->hif_state != HOST_IF_IDLE &&
+                   hif_drv_tmp->hif_state != HOST_IF_CONNECTED) {
+                       PRINT_INFO(vif_tmp->ndev, GENERIC_DBG,
+                                  "Abort scan. In state [%d]\n",
+                                  hif_drv_tmp->hif_state);
+                       result = -EBUSY;
+                       srcu_read_unlock(&vif->wilc->srcu, srcu_idx);
+                       goto error;
+               }
+       }
+       srcu_read_unlock(&vif->wilc->srcu, srcu_idx);
+
+       if (vif->connecting) {
+               PRINT_INFO(vif->ndev, GENERIC_DBG,
+                          "Don't do scan in (CONNECTING) state\n");
+               result = -EBUSY;
+               goto error;
+       }
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Setting SCAN params\n");
+       hif_drv->usr_scan_req.ch_cnt = 0;
+
+       if (request->n_ssids) {
+               for (i = 0; i < request->n_ssids; i++)
+                       valuesize += ((request->ssids[i].ssid_len) + 1);
+               search_ssid_vals = kmalloc(valuesize + 1, GFP_KERNEL);
+               if (search_ssid_vals) {
+                       wid_list[index].id = WID_SSID_PROBE_REQ;
+                       wid_list[index].type = WID_STR;
+                       wid_list[index].val = search_ssid_vals;
+                       buffer = wid_list[index].val;
+
+                       *buffer++ = request->n_ssids;
+
+               PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                          "In Handle_ProbeRequest number of ssid %d\n",
+                        request->n_ssids);
+                       for (i = 0; i < request->n_ssids; i++) {
+                               *buffer++ = request->ssids[i].ssid_len;
+                               memcpy(buffer, request->ssids[i].ssid,
+                                      request->ssids[i].ssid_len);
+                               buffer += request->ssids[i].ssid_len;
+                       }
+                       wid_list[index].size = (s32)(valuesize + 1);
+                       index++;
+               }
+       }
+
+       wid_list[index].id = WID_INFO_ELEMENT_PROBE;
+       wid_list[index].type = WID_BIN_DATA;
+       wid_list[index].val = (s8 *)request->ie;
+       wid_list[index].size = request->ie_len;
+       index++;
+
+       wid_list[index].id = WID_SCAN_TYPE;
+       wid_list[index].type = WID_CHAR;
+       wid_list[index].size = sizeof(char);
+       wid_list[index].val = (s8 *)&scan_type;
+       index++;
+
+#if KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE
+       scan_timeout = WILC_HIF_SCAN_TIMEOUT_MS;
+#else
+       if (scan_type == WILC_FW_PASSIVE_SCAN && request->duration) {
+               wid_list[index].id = WID_PASSIVE_SCAN_TIME;
+               wid_list[index].type = WID_SHORT;
+               wid_list[index].size = sizeof(u16);
+               wid_list[index].val = (s8 *)&request->duration;
+               index++;
+
+               scan_timeout = (request->duration * ch_list_len) + 500;
+       } else {
+               scan_timeout = WILC_HIF_SCAN_TIMEOUT_MS;
+       }
+#endif
+       wid_list[index].id = WID_SCAN_CHANNEL_LIST;
+       wid_list[index].type = WID_BIN_DATA;
+
+       if (ch_freq_list && ch_list_len > 0) {
+               for (i = 0; i < ch_list_len; i++) {
+                       if (ch_freq_list[i] > 0)
+                               ch_freq_list[i] -= 1;
+               }
+       }
+
+       wid_list[index].val = ch_freq_list;
+       wid_list[index].size = ch_list_len;
+       index++;
+
+       wid_list[index].id = WID_START_SCAN_REQ;
+       wid_list[index].type = WID_CHAR;
+       wid_list[index].size = sizeof(char);
+       wid_list[index].val = (s8 *)&scan_source;
+       index++;
+
+       hif_drv->usr_scan_req.scan_result = scan_result_fn;
+       hif_drv->usr_scan_req.arg = user_arg;
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, index);
+       if (result) {
+               PRINT_ER(vif->ndev, "Failed to send scan parameters\n");
+               goto error;
+       } else {
+               hif_drv->scan_timer_vif = vif;
+               PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                          ">> Starting the SCAN timer\n");
+#if KERNEL_VERSION(4, 15, 0) > LINUX_VERSION_CODE
+               hif_drv->scan_timer.data = (unsigned long)hif_drv;
+#endif
+               mod_timer(&hif_drv->scan_timer,
+                         jiffies + msecs_to_jiffies(scan_timeout));
+       }
+
+error:
+
+       kfree(search_ssid_vals);
+
+       return result;
+}
+
+s32 handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
+{
+       s32 result = 0;
+       u8 abort_running_scan;
+       struct wid wid;
+       struct host_if_drv *hif_drv = vif->hif_drv;
+       struct wilc_user_scan_req *scan_req;
+       u8 null_bssid[6] = {0};
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG, "handling scan done\n");
+
+       if (!hif_drv) {
+               PRINT_ER(vif->ndev, "hif driver is NULL\n");
+               return result;
+       }
+
+       if (evt == SCAN_EVENT_DONE) {
+               if (memcmp(hif_drv->assoc_bssid, null_bssid, ETH_ALEN) == 0)
+                       hif_drv->hif_state = HOST_IF_IDLE;
+               else
+                       hif_drv->hif_state = HOST_IF_CONNECTED;
+       } else if (evt == SCAN_EVENT_ABORTED) {
+               PRINT_INFO(vif->ndev, GENERIC_DBG, "Abort running scan\n");
+               abort_running_scan = 1;
+               wid.id = WID_ABORT_RUNNING_SCAN;
+               wid.type = WID_CHAR;
+               wid.val = (s8 *)&abort_running_scan;
+               wid.size = sizeof(char);
+
+               result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+               if (result) {
+                       PRINT_ER(vif->ndev, "Failed to set abort running\n");
+                       result = -EFAULT;
+               }
+       }
+
+       scan_req = &hif_drv->usr_scan_req;
+       if (scan_req->scan_result) {
+               scan_req->scan_result(evt, NULL, scan_req->arg);
+               scan_req->scan_result = NULL;
+       }
+
+       return result;
+}
+
+static int wilc_send_connect_wid(struct wilc_vif *vif)
+{
+       int result = 0;
+       struct wid wid_list[4];
+       u32 wid_cnt = 0;
+       struct host_if_drv *hif_drv = vif->hif_drv;
+       struct wilc_conn_info *conn_attr = &hif_drv->conn_info;
+       struct wilc_join_bss_param *bss_param = hif_drv->conn_info.param;
+       struct wilc_vif *vif_tmp;
+       int srcu_idx;
+
+       srcu_idx = srcu_read_lock(&vif->wilc->srcu);
+       list_for_each_entry_rcu(vif_tmp, &vif->wilc->vif_list, list) {
+               struct host_if_drv *hif_drv_tmp;
+
+               if (vif_tmp == NULL || vif_tmp->hif_drv == NULL)
+                       continue;
+
+               hif_drv_tmp = vif_tmp->hif_drv;
+
+               if (hif_drv_tmp->hif_state == HOST_IF_SCANNING) {
+                       PRINT_INFO(vif_tmp->ndev, GENERIC_DBG,
+                                  "Abort connect in state [%d]\n",
+                                  hif_drv_tmp->hif_state);
+                       result = -EBUSY;
+                       srcu_read_unlock(&vif->wilc->srcu, srcu_idx);
+                       goto error;
+               }
+       }
+       srcu_read_unlock(&vif->wilc->srcu, srcu_idx);
+
+       wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE;
+       wid_list[wid_cnt].type = WID_BIN_DATA;
+       wid_list[wid_cnt].val = conn_attr->req_ies;
+       wid_list[wid_cnt].size = conn_attr->req_ies_len;
+       wid_cnt++;
+
+       wid_list[wid_cnt].id = WID_11I_MODE;
+       wid_list[wid_cnt].type = WID_CHAR;
+       wid_list[wid_cnt].size = sizeof(char);
+       wid_list[wid_cnt].val = (s8 *)&conn_attr->security;
+       wid_cnt++;
+
+       PRINT_D(vif->ndev, HOSTINF_DBG, "Encrypt Mode = %x\n",
+               conn_attr->security);
+       wid_list[wid_cnt].id = WID_AUTH_TYPE;
+       wid_list[wid_cnt].type = WID_CHAR;
+       wid_list[wid_cnt].size = sizeof(char);
+       wid_list[wid_cnt].val = (s8 *)&conn_attr->auth_type;
+       wid_cnt++;
+
+       PRINT_D(vif->ndev, HOSTINF_DBG, "Authentication Type = %x\n",
+               conn_attr->auth_type);
+       PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                  "Connecting to network on channel %d\n", conn_attr->ch);
+
+       wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED;
+       wid_list[wid_cnt].type = WID_STR;
+       wid_list[wid_cnt].size = sizeof(*bss_param);
+       wid_list[wid_cnt].val = (u8 *)bss_param;
+       wid_cnt++;
+
+       PRINT_INFO(vif->ndev, GENERIC_DBG, "send HOST_IF_WAITING_CONN_RESP\n");
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, wid_cnt);
+       if (result) {
+               PRINT_ER(vif->ndev, "failed to send config packet\n");
+               goto error;
+       } else {
+               PRINT_INFO(vif->ndev, GENERIC_DBG,
+                          "set HOST_IF_WAITING_CONN_RESP\n");
+               hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
+       }
+
+       return 0;
+
+error:
+
+       kfree(conn_attr->req_ies);
+       conn_attr->req_ies = NULL;
+
+       return result;
+}
+
+void handle_connect_cancel(struct wilc_vif *vif)
+{
+       struct host_if_drv *hif_drv = vif->hif_drv;
+
+       if (hif_drv->conn_info.conn_result) {
+               hif_drv->conn_info.conn_result(EVENT_DISCONN_NOTIF,
+                                              0, hif_drv->conn_info.arg);
+       }
+
+       eth_zero_addr(hif_drv->assoc_bssid);
+
+       hif_drv->conn_info.req_ies_len = 0;
+       kfree(hif_drv->conn_info.req_ies);
+       hif_drv->conn_info.req_ies = NULL;
+       hif_drv->hif_state = HOST_IF_IDLE;
+}
+
+static void handle_connect_timeout(struct work_struct *work)
+{
+       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
+       struct wilc_vif *vif = msg->vif;
+       int result;
+       struct wid wid;
+       u16 dummy_reason_code = 0;
+       struct host_if_drv *hif_drv = vif->hif_drv;
+
+       if (!hif_drv) {
+               PRINT_ER(vif->ndev, "hif driver is NULL\n");
+               goto out;
+       }
+
+       hif_drv->hif_state = HOST_IF_IDLE;
+
+       if (hif_drv->conn_info.conn_result) {
+               hif_drv->conn_info.conn_result(EVENT_CONN_RESP,
+                                              WILC_MAC_STATUS_DISCONNECTED,
+                                              hif_drv->conn_info.arg);
+
+       } else {
+               PRINT_ER(vif->ndev, "conn_result is NULL\n");
+       }
+
+       wid.id = WID_DISCONNECT;
+       wid.type = WID_CHAR;
+       wid.val = (s8 *)&dummy_reason_code;
+       wid.size = sizeof(char);
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Sending disconnect request\n");
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev, "Failed to send disconect\n");
+
+       hif_drv->conn_info.req_ies_len = 0;
+       kfree(hif_drv->conn_info.req_ies);
+       hif_drv->conn_info.req_ies = NULL;
+
+out:
+       kfree(msg);
+}
+
+void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
+                               struct cfg80211_crypto_settings *crypto)
+{
+       struct wilc_join_bss_param *param;
+       struct ieee80211_p2p_noa_attr noa_attr;
+       u8 rates_len = 0;
+       const u8 *tim_elm, *ssid_elm, *rates_ie, *supp_rates_ie;
+       const u8 *ht_ie, *wpa_ie, *wmm_ie, *rsn_ie;
+       int ret;
+       const struct cfg80211_bss_ies *ies = rcu_dereference(bss->ies);
+
+       param = kzalloc(sizeof(*param), GFP_KERNEL);
+       if (!param)
+               return NULL;
+
+       param->beacon_period = cpu_to_le16(bss->beacon_interval);
+       param->cap_info = cpu_to_le16(bss->capability);
+       param->bss_type = WILC_FW_BSS_TYPE_INFRA;
+       param->ch = ieee80211_frequency_to_channel(bss->channel->center_freq);
+       ether_addr_copy(param->bssid, bss->bssid);
+
+       ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
+       if (ssid_elm) {
+               if (ssid_elm[1] <= IEEE80211_MAX_SSID_LEN)
+                       memcpy(param->ssid, ssid_elm + 2, ssid_elm[1]);
+       }
+
+       tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len);
+       if (tim_elm && tim_elm[1] >= 2)
+               param->dtim_period = tim_elm[3];
+
+       memset(param->p_suites, 0xFF, 3);
+       memset(param->akm_suites, 0xFF, 3);
+
+       rates_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies->data, ies->len);
+       if (rates_ie) {
+               rates_len = rates_ie[1];
+               if (rates_len > WILC_MAX_RATES_SUPPORTED)
+                       rates_len = WILC_MAX_RATES_SUPPORTED;
+               param->supp_rates[0] = rates_len;
+               memcpy(&param->supp_rates[1], rates_ie + 2, rates_len);
+       }
+
+       supp_rates_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, ies->data,
+                                        ies->len);
+       if (supp_rates_ie) {
+               if (supp_rates_ie[1] > (WILC_MAX_RATES_SUPPORTED - rates_len))
+                       param->supp_rates[0] = WILC_MAX_RATES_SUPPORTED;
+               else
+                       param->supp_rates[0] += supp_rates_ie[1];
+
+               memcpy(&param->supp_rates[rates_len + 1], supp_rates_ie + 2,
+                      (param->supp_rates[0] - rates_len));
+       }
+
+       ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies->data, ies->len);
+       if (ht_ie)
+               param->ht_capable = true;
+
+       ret = cfg80211_get_p2p_attr(ies->data, ies->len,
+                                   IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
+                                   (u8 *)&noa_attr, sizeof(noa_attr));
+       if (ret > 0) {
+               param->tsf_lo = cpu_to_le32(ies->tsf);
+               param->noa_enabled = 1;
+               param->idx = noa_attr.index;
+               if (noa_attr.oppps_ctwindow & IEEE80211_P2P_OPPPS_ENABLE_BIT) {
+                       param->opp_enabled = 1;
+                       param->opp_en.ct_window = noa_attr.oppps_ctwindow;
+                       param->opp_en.cnt = noa_attr.desc[0].count;
+                       param->opp_en.duration = noa_attr.desc[0].duration;
+                       param->opp_en.interval = noa_attr.desc[0].interval;
+                       param->opp_en.start_time = noa_attr.desc[0].start_time;
+               } else {
+                       param->opp_enabled = 0;
+                       param->opp_dis.cnt = noa_attr.desc[0].count;
+                       param->opp_dis.duration = noa_attr.desc[0].duration;
+                       param->opp_dis.interval = noa_attr.desc[0].interval;
+                       param->opp_dis.start_time = noa_attr.desc[0].start_time;
+               }
+       }
+       wmm_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+                                        WLAN_OUI_TYPE_MICROSOFT_WMM,
+                                        ies->data, ies->len);
+       if (wmm_ie) {
+               struct ieee80211_wmm_param_ie *ie;
+
+               ie = (struct ieee80211_wmm_param_ie *)wmm_ie;
+               if ((ie->oui_subtype == 0 || ie->oui_subtype == 1) &&
+                   ie->version == 1) {
+                       param->wmm_cap = true;
+                       if (ie->qos_info & BIT(7))
+                               param->uapsd_cap = true;
+               }
+       }
+
+       wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+                                        WLAN_OUI_TYPE_MICROSOFT_WPA,
+                                        ies->data, ies->len);
+       if (wpa_ie) {
+               param->mode_802_11i = 1;
+               param->rsn_found = true;
+       }
+
+       rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, ies->data, ies->len);
+       if (rsn_ie) {
+               int offset = 8;
+
+               param->mode_802_11i = 2;
+               param->rsn_found = true;
+               //extract RSN capabilities
+               offset += (rsn_ie[offset] * 4) + 2;
+               offset += (rsn_ie[offset] * 4) + 2;
+               memcpy(param->rsn_cap, &rsn_ie[offset], 2);
+       }
+
+       if (param->rsn_found) {
+               int i;
+
+               param->rsn_grp_policy = crypto->cipher_group & 0xFF;
+               for (i = 0; i < crypto->n_ciphers_pairwise && i < 3; i++)
+                       param->p_suites[i] = crypto->ciphers_pairwise[i] & 0xFF;
+
+               for (i = 0; i < crypto->n_akm_suites && i < 3; i++)
+                       param->akm_suites[i] = crypto->akm_suites[i] & 0xFF;
+       }
+
+       return (void *)param;
+}
+
+static void handle_rcvd_ntwrk_info(struct work_struct *work)
+{
+       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
+       struct wilc_rcvd_net_info *rcvd_info = &msg->body.net_info;
+       struct wilc_user_scan_req *scan_req = &msg->vif->hif_drv->usr_scan_req;
+       const u8 *ch_elm;
+       u8 *ies;
+       int ies_len;
+       size_t offset;
+
+       PRINT_D(msg->vif->ndev, HOSTINF_DBG,
+               "Handling received network info\n");
+
+       if (ieee80211_is_probe_resp(rcvd_info->mgmt->frame_control))
+               offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+       else if (ieee80211_is_beacon(rcvd_info->mgmt->frame_control))
+               offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
+       else
+               goto done;
+
+       ies = rcvd_info->mgmt->u.beacon.variable;
+       ies_len = rcvd_info->frame_len - offset;
+       if (ies_len <= 0)
+               goto done;
+
+       PRINT_INFO(msg->vif->ndev, HOSTINF_DBG, "New network found\n");
+       /* extract the channel from recevied mgmt frame */
+       ch_elm = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_len);
+       if (ch_elm && ch_elm[1] > 0)
+               rcvd_info->ch = ch_elm[2];
+
+       if (scan_req->scan_result)
+               scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND,
+                                     rcvd_info, scan_req->arg);
+
+done:
+       kfree(rcvd_info->mgmt);
+       kfree(msg);
+}
+
+static void host_int_get_assoc_res_info(struct wilc_vif *vif,
+                                       u8 *assoc_resp_info,
+                                       u32 max_assoc_resp_info_len,
+                                       u32 *rcvd_assoc_resp_info_len)
+{
+       int result;
+       struct wid wid;
+
+       wid.id = WID_ASSOC_RES_INFO;
+       wid.type = WID_STR;
+       wid.val = assoc_resp_info;
+       wid.size = max_assoc_resp_info_len;
+
+       result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
+       if (result) {
+               *rcvd_assoc_resp_info_len = 0;
+               PRINT_ER(vif->ndev, "Failed to send association response\n");
+               return;
+       }
+
+       *rcvd_assoc_resp_info_len = wid.size;
+}
+
+static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len,
+                                     struct wilc_conn_info *ret_conn_info)
+{
+       u8 *ies;
+       u16 ies_len;
+       struct assoc_resp *res = (struct assoc_resp *)buffer;
+
+       ret_conn_info->status = le16_to_cpu(res->status_code);
+       if (ret_conn_info->status == WLAN_STATUS_SUCCESS) {
+               ies = &buffer[sizeof(*res)];
+               ies_len = buffer_len - sizeof(*res);
+
+               ret_conn_info->resp_ies = kmemdup(ies, ies_len, GFP_KERNEL);
+               if (!ret_conn_info->resp_ies)
+                       return -ENOMEM;
+
+               ret_conn_info->resp_ies_len = ies_len;
+       }
+
+       return 0;
+}
+
+static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
+                                                 u8 mac_status)
+{
+       struct host_if_drv *hif_drv = vif->hif_drv;
+       struct wilc_conn_info *conn_info = &hif_drv->conn_info;
+
+       if (mac_status == WILC_MAC_STATUS_CONNECTED) {
+               u32 assoc_resp_info_len;
+
+               memset(hif_drv->assoc_resp, 0, WILC_MAX_ASSOC_RESP_FRAME_SIZE);
+
+               host_int_get_assoc_res_info(vif, hif_drv->assoc_resp,
+                                           WILC_MAX_ASSOC_RESP_FRAME_SIZE,
+                                           &assoc_resp_info_len);
+
+               PRINT_D(vif->ndev, HOSTINF_DBG,
+                       "Received association response = %d\n",
+                       assoc_resp_info_len);
+               if (assoc_resp_info_len != 0) {
+                       s32 err = 0;
+
+                       PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                                  "Parsing association response\n");
+                       err = wilc_parse_assoc_resp_info(hif_drv->assoc_resp,
+                                                        assoc_resp_info_len,
+                                                        conn_info);
+                       if (err)
+                               PRINT_ER(vif->ndev,
+                                        "wilc_parse_assoc_resp_info() returned error %d\n",
+                                        err);
+               }
+       }
+
+       del_timer(&hif_drv->connect_timer);
+       conn_info->conn_result(EVENT_CONN_RESP, mac_status, conn_info->arg);
+
+       if (mac_status == WILC_MAC_STATUS_CONNECTED &&
+           conn_info->status == WLAN_STATUS_SUCCESS) {
+               PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                          "MAC status : CONNECTED and Connect Status : Successful\n");
+               hif_drv->hif_state = HOST_IF_CONNECTED;
+               ether_addr_copy(hif_drv->assoc_bssid, conn_info->bssid);
+       } else {
+               PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                          "MAC status : %d and Connect Status : %d\n",
+                          mac_status, conn_info->status);
+               hif_drv->hif_state = HOST_IF_IDLE;
+       }
+
+       kfree(conn_info->resp_ies);
+       conn_info->resp_ies = NULL;
+       conn_info->resp_ies_len = 0;
+
+       kfree(conn_info->req_ies);
+       conn_info->req_ies = NULL;
+       conn_info->req_ies_len = 0;
+}
+
+static inline void host_int_handle_disconnect(struct wilc_vif *vif)
+{
+       struct host_if_drv *hif_drv = vif->hif_drv;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                  "Received WILC_MAC_STATUS_DISCONNECTED from the FW\n");
+       if (hif_drv->usr_scan_req.scan_result) {
+               PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                          "\n\n<< Abort the running OBSS Scan >>\n\n");
+               del_timer(&hif_drv->scan_timer);
+               handle_scan_done(vif, SCAN_EVENT_ABORTED);
+       }
+
+       if (hif_drv->conn_info.conn_result) {
+               hif_drv->conn_info.conn_result(EVENT_DISCONN_NOTIF,
+                                              0, hif_drv->conn_info.arg);
+       } else {
+               PRINT_ER(vif->ndev, "Connect result NULL\n");
+       }
+
+       eth_zero_addr(hif_drv->assoc_bssid);
+
+       hif_drv->conn_info.req_ies_len = 0;
+       kfree(hif_drv->conn_info.req_ies);
+       hif_drv->conn_info.req_ies = NULL;
+       hif_drv->hif_state = HOST_IF_IDLE;
+}
+
+static void handle_rcvd_gnrl_async_info(struct work_struct *work)
+{
+       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
+       struct wilc_vif *vif = msg->vif;
+       struct wilc_rcvd_mac_info *mac_info = &msg->body.mac_info;
+       struct host_if_drv *hif_drv = vif->hif_drv;
+
+       if (!hif_drv) {
+               netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
+               goto free_msg;
+       }
+
+       PRINT_INFO(vif->ndev, GENERIC_DBG,
+                  "Current State = %d,Received state = %d\n",
+                  hif_drv->hif_state, mac_info->status);
+
+       if (!hif_drv->conn_info.conn_result) {
+               PRINT_ER(vif->ndev, "conn_result is NULL\n");
+               goto free_msg;
+       }
+       if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
+               host_int_parse_assoc_resp_info(vif, mac_info->status);
+       } else if (mac_info->status == WILC_MAC_STATUS_DISCONNECTED) {
+               if (hif_drv->hif_state == HOST_IF_CONNECTED) {
+                       host_int_handle_disconnect(vif);
+               } else if (hif_drv->usr_scan_req.scan_result) {
+                       PRINT_WRN(vif->ndev, HOSTINF_DBG,
+                                 "Received WILC_MAC_STATUS_DISCONNECTED. Abort the running Scan");
+                       del_timer(&hif_drv->scan_timer);
+                       handle_scan_done(vif, SCAN_EVENT_ABORTED);
+               }
+       }
+
+free_msg:
+       kfree(msg);
+}
+
+int wilc_disconnect(struct wilc_vif *vif)
+{
+       struct wid wid;
+       struct host_if_drv *hif_drv = vif->hif_drv;
+       struct wilc_user_scan_req *scan_req;
+       struct wilc_conn_info *conn_info;
+       int result;
+       u16 dummy_reason_code = 0;
+       struct wilc_vif *vif_tmp;
+       int srcu_idx;
+
+       srcu_idx = srcu_read_lock(&vif->wilc->srcu);
+       list_for_each_entry_rcu(vif_tmp, &vif->wilc->vif_list, list) {
+               struct host_if_drv *hif_drv_tmp;
+
+               if (vif_tmp == NULL || vif_tmp->hif_drv == NULL)
+                       continue;
+
+               hif_drv_tmp = vif_tmp->hif_drv;
+
+               if (hif_drv_tmp->hif_state == HOST_IF_SCANNING) {
+                       PRINT_INFO(vif_tmp->ndev, GENERIC_DBG,
+                                  "Abort scan from disconnect. state [%d]\n",
+                                  hif_drv_tmp->hif_state);
+                       del_timer(&hif_drv_tmp->scan_timer);
+                       handle_scan_done(vif_tmp, SCAN_EVENT_ABORTED);
+               }
+       }
+       srcu_read_unlock(&vif->wilc->srcu, srcu_idx);
+
+       wid.id = WID_DISCONNECT;
+       wid.type = WID_CHAR;
+       wid.val = (s8 *)&dummy_reason_code;
+       wid.size = sizeof(char);
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Sending disconnect request\n");
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result) {
+               PRINT_ER(vif->ndev, "Failed to send disconnect\n");
+               return -ENOMEM;
+       }
+
+       scan_req = &hif_drv->usr_scan_req;
+       conn_info = &hif_drv->conn_info;
+
+       if (scan_req->scan_result) {
+               del_timer(&hif_drv->scan_timer);
+               scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg);
+               scan_req->scan_result = NULL;
+       }
+
+       if (conn_info->conn_result) {
+               if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
+                       PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                                  "supplicant requested disconnection\n");
+                       del_timer(&hif_drv->connect_timer);
+                       conn_info->conn_result(EVENT_CONN_RESP,
+                                              WILC_MAC_STATUS_DISCONNECTED,
+                                              conn_info->arg);
+
+               } else if (hif_drv->hif_state == HOST_IF_CONNECTED) {
+                       conn_info->conn_result(EVENT_DISCONN_NOTIF,
+                                              WILC_MAC_STATUS_DISCONNECTED,
+                                              conn_info->arg);
+               }
+       } else {
+               PRINT_ER(vif->ndev, "conn_result = NULL\n");
+       }
+
+       hif_drv->hif_state = HOST_IF_IDLE;
+
+       eth_zero_addr(hif_drv->assoc_bssid);
+
+       conn_info->req_ies_len = 0;
+       kfree(conn_info->req_ies);
+       conn_info->req_ies = NULL;
+       conn_info->conn_result = NULL;
+
+       return 0;
+}
+
+int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
+{
+       struct wid wid_list[5];
+       u32 wid_cnt = 0, result;
+
+       wid_list[wid_cnt].id = WID_LINKSPEED;
+       wid_list[wid_cnt].type = WID_CHAR;
+       wid_list[wid_cnt].size = sizeof(char);
+       wid_list[wid_cnt].val = (s8 *)&stats->link_speed;
+       wid_cnt++;
+
+       wid_list[wid_cnt].id = WID_RSSI;
+       wid_list[wid_cnt].type = WID_CHAR;
+       wid_list[wid_cnt].size = sizeof(char);
+       wid_list[wid_cnt].val = (s8 *)&stats->rssi;
+       wid_cnt++;
+
+       wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
+       wid_list[wid_cnt].type = WID_INT;
+       wid_list[wid_cnt].size = sizeof(u32);
+       wid_list[wid_cnt].val = (s8 *)&stats->tx_cnt;
+       wid_cnt++;
+
+       wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT;
+       wid_list[wid_cnt].type = WID_INT;
+       wid_list[wid_cnt].size = sizeof(u32);
+       wid_list[wid_cnt].val = (s8 *)&stats->rx_cnt;
+       wid_cnt++;
+
+       wid_list[wid_cnt].id = WID_FAILED_COUNT;
+       wid_list[wid_cnt].type = WID_INT;
+       wid_list[wid_cnt].size = sizeof(u32);
+       wid_list[wid_cnt].val = (s8 *)&stats->tx_fail_cnt;
+       wid_cnt++;
+
+       result = wilc_send_config_pkt(vif, WILC_GET_CFG, wid_list, wid_cnt);
+       if (result) {
+               PRINT_ER(vif->ndev, "Failed to send scan parameters\n");
+               return result;
+       }
+
+       if (stats->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
+           stats->link_speed != DEFAULT_LINK_SPEED) {
+               PRINT_INFO(vif->ndev, HOSTINF_DBG, "Enable TCP filter\n");
+               wilc_enable_tcp_ack_filter(vif, true);
+       } else if (stats->link_speed != DEFAULT_LINK_SPEED) {
+               PRINT_INFO(vif->ndev, HOSTINF_DBG, "Disable TCP filter %d\n",
+                          stats->link_speed);
+               wilc_enable_tcp_ack_filter(vif, false);
+       }
+
+       return result;
+}
+
+static void handle_get_statistics(struct work_struct *work)
+{
+       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
+       struct wilc_vif *vif = msg->vif;
+       struct rf_info *stats = (struct rf_info *)msg->body.data;
+
+       wilc_get_statistics(vif, stats);
+       kfree(msg);
+}
+
+static void wilc_hif_pack_sta_param(struct wilc_vif *vif, u8 *cur_byte,
+                                   const u8 *mac,
+                                   struct station_parameters *params)
+{
+       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Packing STA params\n");
+       ether_addr_copy(cur_byte, mac);
+       cur_byte +=  ETH_ALEN;
+
+       put_unaligned_le16(params->aid, cur_byte);
+       cur_byte += 2;
+
+       *cur_byte++ = params->supported_rates_len;
+       if (params->supported_rates_len > 0)
+               memcpy(cur_byte, params->supported_rates,
+                      params->supported_rates_len);
+       cur_byte += params->supported_rates_len;
+
+       if (params->ht_capa) {
+               *cur_byte++ = true;
+               memcpy(cur_byte, &params->ht_capa,
+                      sizeof(struct ieee80211_ht_cap));
+       } else {
+               *cur_byte++ = false;
+       }
+       cur_byte += sizeof(struct ieee80211_ht_cap);
+
+       put_unaligned_le16(params->sta_flags_mask, cur_byte);
+       cur_byte += 2;
+       put_unaligned_le16(params->sta_flags_set, cur_byte);
+}
+
+static int handle_remain_on_chan(struct wilc_vif *vif,
+                                struct wilc_remain_ch *hif_remain_ch)
+{
+       int result;
+       u8 remain_on_chan_flag;
+       struct wid wid;
+       struct host_if_drv *hif_drv = vif->hif_drv;
+       struct wilc_vif *vif_tmp;
+       int srcu_idx;
+
+       if (!hif_drv) {
+               PRINT_ER(vif->ndev, "Driver is null\n");
+               return -EFAULT;
+       }
+
+       srcu_idx = srcu_read_lock(&vif->wilc->srcu);
+       list_for_each_entry_rcu(vif_tmp, &vif->wilc->vif_list, list) {
+               struct host_if_drv *hif_drv_tmp;
+
+               if (vif_tmp == NULL || vif_tmp->hif_drv == NULL)
+                       continue;
+
+               hif_drv_tmp = vif_tmp->hif_drv;
+
+               if (hif_drv_tmp->hif_state == HOST_IF_SCANNING) {
+                       PRINT_INFO(vif_tmp->ndev, GENERIC_DBG,
+                                  "IFC busy scanning. WLAN_IFC state %d\n",
+                                  hif_drv_tmp->hif_state);
+                       srcu_read_unlock(&vif->wilc->srcu, srcu_idx);
+                       return -EBUSY;
+               } else if (hif_drv_tmp->hif_state != HOST_IF_IDLE &&
+                          hif_drv_tmp->hif_state != HOST_IF_CONNECTED) {
+                       PRINT_INFO(vif_tmp->ndev, GENERIC_DBG,
+                                  "IFC busy connecting. WLAN_IFC %d\n",
+                                  hif_drv_tmp->hif_state);
+                       srcu_read_unlock(&vif->wilc->srcu, srcu_idx);
+                       return -EBUSY;
+               }
+       }
+       srcu_read_unlock(&vif->wilc->srcu, srcu_idx);
+
+       if (vif->connecting) {
+               PRINT_INFO(vif->ndev, GENERIC_DBG,
+                          "Don't do scan in (CONNECTING) state\n");
+               return -EBUSY;
+       }
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                  "Setting channel [%d] duration[%d] [%llu]\n",
+                  hif_remain_ch->ch, hif_remain_ch->duration,
+                  hif_remain_ch->cookie);
+       remain_on_chan_flag = true;
+       wid.id = WID_REMAIN_ON_CHAN;
+       wid.type = WID_STR;
+       wid.size = 2;
+       wid.val = kmalloc(wid.size, GFP_KERNEL);
+       if (!wid.val)
+               return -ENOMEM;
+
+       wid.val[0] = remain_on_chan_flag;
+       wid.val[1] = (s8)hif_remain_ch->ch;
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       kfree(wid.val);
+       if (result) {
+               PRINT_ER(vif->ndev, "Failed to set remain on channel\n");
+               return -EBUSY;
+       }
+
+       hif_drv->remain_on_ch.arg = hif_remain_ch->arg;
+       hif_drv->remain_on_ch.expired = hif_remain_ch->expired;
+       hif_drv->remain_on_ch.ch = hif_remain_ch->ch;
+       hif_drv->remain_on_ch.cookie = hif_remain_ch->cookie;
+       hif_drv->hif_state = HOST_IF_P2P_LISTEN;
+
+       hif_drv->remain_on_ch_timer_vif = vif;
+
+       return result;
+}
+
+static int handle_roc_expired(struct wilc_vif *vif, u64 cookie)
+{
+       u8 remain_on_chan_flag;
+       struct wid wid;
+       int result;
+       struct host_if_drv *hif_drv = vif->hif_drv;
+       u8 null_bssid[6] = {0};
+
+       if (hif_drv->hif_state == HOST_IF_P2P_LISTEN) {
+               remain_on_chan_flag = false;
+               wid.id = WID_REMAIN_ON_CHAN;
+               wid.type = WID_STR;
+               wid.size = 2;
+               wid.val = kmalloc(wid.size, GFP_KERNEL);
+               if (!wid.val) {
+                       PRINT_ER(vif->ndev, "Failed to allocate memory\n");
+                       return -ENOMEM;
+               }
+
+               wid.val[0] = remain_on_chan_flag;
+               wid.val[1] = WILC_FALSE_FRMWR_CHANNEL;
+
+               result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+               kfree(wid.val);
+               if (result != 0) {
+                       PRINT_ER(vif->ndev, "Failed to set remain channel\n");
+                       return -ENOMEM;
+               }
+
+               if (hif_drv->remain_on_ch.expired)
+                       hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
+                                                     cookie);
+
+               if (memcmp(hif_drv->assoc_bssid, null_bssid, ETH_ALEN) == 0)
+                       hif_drv->hif_state = HOST_IF_IDLE;
+               else
+                       hif_drv->hif_state = HOST_IF_CONNECTED;
+       } else {
+               PRINT_D(vif->ndev, GENERIC_DBG,  "Not in listen state\n");
+       }
+
+       return 0;
+}
+
+static void handle_listen_state_expired(struct work_struct *work)
+{
+       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
+       struct wilc_vif *vif = msg->vif;
+       struct wilc_remain_ch *hif_remain_ch = &msg->body.remain_on_ch;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG, "CANCEL REMAIN ON CHAN\n");
+
+       handle_roc_expired(vif, hif_remain_ch->cookie);
+
+       kfree(msg);
+}
+
+#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
+static void listen_timer_cb(struct timer_list *t)
+#else
+static void listen_timer_cb(unsigned long arg)
+#endif
+{
+#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
+       struct host_if_drv *hif_drv = from_timer(hif_drv, t,
+                                                     remain_on_ch_timer);
+#else
+       struct host_if_drv *hif_drv = (struct host_if_drv *)arg;
+#endif
+       struct wilc_vif *vif = hif_drv->remain_on_ch_timer_vif;
+       int result;
+       struct host_if_msg *msg;
+
+       del_timer(&vif->hif_drv->remain_on_ch_timer);
+
+       msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
+       if (IS_ERR(msg))
+               return;
+
+       msg->body.remain_on_ch.cookie = vif->hif_drv->remain_on_ch.cookie;
+
+       result = wilc_enqueue_work(msg);
+       if (result) {
+               PRINT_ER(vif->ndev, "wilc_mq_send fail\n");
+               kfree(msg);
+       }
+}
+
+static void handle_set_mcast_filter(struct work_struct *work)
+{
+       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
+       struct wilc_vif *vif = msg->vif;
+       struct wilc_set_multicast *set_mc = &msg->body.mc_info;
+       int result;
+       struct wid wid;
+       u8 *cur_byte;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Setup Multicast Filter\n");
+
+       wid.id = WID_SETUP_MULTICAST_FILTER;
+       wid.type = WID_BIN;
+       wid.size = sizeof(struct wilc_set_multicast) + (set_mc->cnt * ETH_ALEN);
+       wid.val = kmalloc(wid.size, GFP_KERNEL);
+       if (!wid.val)
+               goto error;
+
+       cur_byte = wid.val;
+       put_unaligned_le32(set_mc->enabled, cur_byte);
+       cur_byte += 4;
+
+       put_unaligned_le32(set_mc->cnt, cur_byte);
+       cur_byte += 4;
+
+       if (set_mc->cnt > 0 && set_mc->mc_list)
+               memcpy(cur_byte, set_mc->mc_list, set_mc->cnt * ETH_ALEN);
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev, "Failed to send setup multicast\n");
+
+error:
+       kfree(set_mc->mc_list);
+       kfree(wid.val);
+       kfree(msg);
+}
+
+void wilc_set_wowlan_trigger(struct wilc_vif *vif, u8 wowlan_trigger)
+{
+       int ret;
+       struct wid wid;
+
+       wid.id = WID_WOWLAN_TRIGGER;
+       wid.type = WID_CHAR;
+       wid.val = &wowlan_trigger;
+       wid.size = sizeof(s8);
+
+       ret = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (ret)
+               PRINT_ER(vif->ndev,
+                        "Failed to send wowlan trigger config packet\n");
+}
+
+static void handle_scan_timer(struct work_struct *work)
+{
+       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
+       int ret;
+
+       PRINT_INFO(msg->vif->ndev, HOSTINF_DBG, "handling scan timer\n");
+       ret = handle_scan_done(msg->vif, SCAN_EVENT_ABORTED);
+       if (ret)
+               PRINT_ER(msg->vif->ndev, "Failed to handle scan done\n");
+       kfree(msg);
+}
+
+static void handle_scan_complete(struct work_struct *work)
+{
+       struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
+
+       del_timer(&msg->vif->hif_drv->scan_timer);
+       PRINT_INFO(msg->vif->ndev, HOSTINF_DBG, "scan completed\n");
+
+       handle_scan_done(msg->vif, SCAN_EVENT_DONE);
+
+       kfree(msg);
+}
+
+#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
+static void timer_scan_cb(struct timer_list *t)
+#else
+static void timer_scan_cb(unsigned long arg)
+#endif
+{
+#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
+       struct host_if_drv *hif_drv = from_timer(hif_drv, t, scan_timer);
+#else
+       struct host_if_drv *hif_drv = (struct host_if_drv *)arg;
+#endif
+       struct wilc_vif *vif = hif_drv->scan_timer_vif;
+       struct host_if_msg *msg;
+       int result;
+
+       msg = wilc_alloc_work(vif, handle_scan_timer, false);
+       if (IS_ERR(msg))
+               return;
+
+       result = wilc_enqueue_work(msg);
+       if (result)
+               kfree(msg);
+}
+
+#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
+static void timer_connect_cb(struct timer_list *t)
+#else
+static void timer_connect_cb(unsigned long arg)
+#endif
+{
+#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
+       struct host_if_drv *hif_drv = from_timer(hif_drv, t, connect_timer);
+#else
+       struct host_if_drv *hif_drv = (struct host_if_drv *)arg;
+#endif
+       struct wilc_vif *vif = hif_drv->connect_timer_vif;
+       struct host_if_msg *msg;
+       int result;
+
+       msg = wilc_alloc_work(vif, handle_connect_timeout, false);
+       if (IS_ERR(msg))
+               return;
+
+       result = wilc_enqueue_work(msg);
+       if (result)
+               kfree(msg);
+}
+
+signed int wilc_send_buffered_eap(struct wilc_vif *vif,
+                                 void (*deliver_to_stack)(struct wilc_vif *,
+                                                          u8 *, u32, u32, u8),
+                                 void (*eap_buf_param)(void *), u8 *buff,
+                                 unsigned int size, unsigned int pkt_offset,
+                                 void *user_arg)
+{
+       int result;
+       struct host_if_msg *msg;
+
+       if (!vif || !deliver_to_stack || !eap_buf_param)
+               return -EFAULT;
+
+       msg = wilc_alloc_work(vif, handle_send_buffered_eap, false);
+       if (IS_ERR(msg))
+               return PTR_ERR(msg);
+       msg->body.send_buff_eap.deliver_to_stack = deliver_to_stack;
+       msg->body.send_buff_eap.eap_buf_param = eap_buf_param;
+       msg->body.send_buff_eap.size = size;
+       msg->body.send_buff_eap.pkt_offset = pkt_offset;
+       msg->body.send_buff_eap.buff = kmalloc(size + pkt_offset,
+                                                 GFP_ATOMIC);
+       memcpy(msg->body.send_buff_eap.buff, buff, size + pkt_offset);
+       msg->body.send_buff_eap.user_arg = user_arg;
+
+       result = wilc_enqueue_work(msg);
+       if (result) {
+               PRINT_ER(vif->ndev, "enqueue work failed\n");
+               kfree(msg->body.send_buff_eap.buff);
+               kfree(msg);
+       }
+       return result;
+}
+
+int wilc_remove_wep_key(struct wilc_vif *vif, u8 index)
+{
+       struct wid wid;
+       int result;
+
+       wid.id = WID_REMOVE_WEP_KEY;
+       wid.type = WID_STR;
+       wid.size = sizeof(char);
+       wid.val = &index;
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev,
+                        "Failed to send remove wep key config packet\n");
+       return result;
+}
+
+int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index)
+{
+       struct wid wid;
+       int result;
+
+       wid.id = WID_KEY_ID;
+       wid.type = WID_CHAR;
+       wid.size = sizeof(char);
+       wid.val = &index;
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev,
+                        "Failed to send wep default key config packet\n");
+
+       return result;
+}
+
+int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
+                            u8 index)
+{
+       struct wid wid;
+       int result;
+       struct wilc_wep_key *wep_key;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Handling WEP key\n");
+       wid.id = WID_ADD_WEP_KEY;
+       wid.type = WID_STR;
+       wid.size = sizeof(*wep_key) + len;
+       wep_key = kzalloc(wid.size, GFP_KERNEL);
+       if (!wep_key) {
+               PRINT_ER(vif->ndev, "No buffer to send Key\n");
+               return -ENOMEM;
+       }
+       wid.val = (u8 *)wep_key;
+
+       wep_key->index = index;
+       wep_key->key_len = len;
+       memcpy(wep_key->key, key, len);
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               netdev_err(vif->ndev,
+                          "Failed to add wep key config packet\n");
+
+       kfree(wep_key);
+       return result;
+}
+
+int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
+                           u8 index, u8 mode, enum authtype auth_type)
+{
+       struct wid wid_list[3];
+       int result;
+       struct wilc_wep_key *wep_key;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG, "Handling WEP key index: %d\n",
+                  index);
+       wid_list[0].id = WID_11I_MODE;
+       wid_list[0].type = WID_CHAR;
+       wid_list[0].size = sizeof(char);
+       wid_list[0].val = &mode;
+
+       wid_list[1].id = WID_AUTH_TYPE;
+       wid_list[1].type = WID_CHAR;
+       wid_list[1].size = sizeof(char);
+       wid_list[1].val = (s8 *)&auth_type;
+
+       wid_list[2].id = WID_WEP_KEY_VALUE;
+       wid_list[2].type = WID_STR;
+       wid_list[2].size = sizeof(*wep_key) + len;
+       wep_key = kzalloc(wid_list[2].size, GFP_KERNEL);
+       if (!wep_key) {
+               PRINT_ER(vif->ndev, "No buffer to send Key\n");
+               return -ENOMEM;
+       }
+
+       wid_list[2].val = (u8 *)wep_key;
+
+       wep_key->index = index;
+       wep_key->key_len = len;
+       memcpy(wep_key->key, key, len);
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
+                                     ARRAY_SIZE(wid_list));
+       if (result)
+               PRINT_ER(vif->ndev,
+                        "Failed to add wep ap key config packet\n");
+
+       kfree(wep_key);
+       return result;
+}
+
+int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
+                const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
+                u8 mode, u8 cipher_mode, u8 index)
+{
+       int result = 0;
+       u8 t_key_len = ptk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
+
+       if (mode == WILC_AP_MODE) {
+               struct wid wid_list[2];
+               struct wilc_ap_wpa_ptk *key_buf;
+
+               wid_list[0].id = WID_11I_MODE;
+               wid_list[0].type = WID_CHAR;
+               wid_list[0].size = sizeof(char);
+               wid_list[0].val = (s8 *)&cipher_mode;
+
+               key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
+               if (!key_buf) {
+                       PRINT_ER(vif->ndev,
+                                "NO buffer to keep Key buffer - AP\n");
+                       return -ENOMEM;
+               }
+               ether_addr_copy(key_buf->mac_addr, mac_addr);
+               key_buf->index = index;
+               key_buf->key_len = t_key_len;
+               memcpy(&key_buf->key[0], ptk, ptk_key_len);
+
+               if (rx_mic)
+                       memcpy(&key_buf->key[ptk_key_len], rx_mic,
+                              WILC_RX_MIC_KEY_LEN);
+
+               if (tx_mic)
+                       memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
+                              tx_mic, WILC_TX_MIC_KEY_LEN);
+
+               wid_list[1].id = WID_ADD_PTK;
+               wid_list[1].type = WID_STR;
+               wid_list[1].size = sizeof(*key_buf) + t_key_len;
+               wid_list[1].val = (u8 *)key_buf;
+               result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
+                                             ARRAY_SIZE(wid_list));
+               kfree(key_buf);
+       } else if (mode == WILC_STATION_MODE) {
+               struct wid wid;
+               struct wilc_sta_wpa_ptk *key_buf;
+
+               key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
+               if (!key_buf) {
+                       PRINT_ER(vif->ndev,
+                                "No buffer to keep Key buffer - Station\n");
+                       return -ENOMEM;
+               }
+
+               ether_addr_copy(key_buf->mac_addr, mac_addr);
+               key_buf->key_len = t_key_len;
+               memcpy(&key_buf->key[0], ptk, ptk_key_len);
+
+               if (rx_mic)
+                       memcpy(&key_buf->key[ptk_key_len], rx_mic,
+                              WILC_RX_MIC_KEY_LEN);
+
+               if (tx_mic)
+                       memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
+                              tx_mic, WILC_TX_MIC_KEY_LEN);
+
+               wid.id = WID_ADD_PTK;
+               wid.type = WID_STR;
+               wid.size = sizeof(*key_buf) + t_key_len;
+               wid.val = (s8 *)key_buf;
+               result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+               kfree(key_buf);
+       }
+
+       return result;
+}
+
+int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
+                   u8 index, u32 key_rsc_len, const u8 *key_rsc,
+                   const u8 *rx_mic, const u8 *tx_mic, u8 mode,
+                   u8 cipher_mode)
+{
+       int result = 0;
+       struct wilc_gtk_key *gtk_key;
+       int t_key_len = gtk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
+
+       gtk_key = kzalloc(sizeof(*gtk_key) + t_key_len, GFP_KERNEL);
+       if (!gtk_key) {
+               PRINT_ER(vif->ndev, "No buffer to send GTK Key\n");
+               return -ENOMEM;
+       }
+
+       /* fill bssid value only in station mode */
+       if (mode == WILC_STATION_MODE &&
+           vif->hif_drv->hif_state == HOST_IF_CONNECTED)
+               memcpy(gtk_key->mac_addr, vif->hif_drv->assoc_bssid, ETH_ALEN);
+
+       if (key_rsc)
+               memcpy(gtk_key->rsc, key_rsc, 8);
+       gtk_key->index = index;
+       gtk_key->key_len = t_key_len;
+       memcpy(&gtk_key->key[0], rx_gtk, gtk_key_len);
+
+       if (rx_mic)
+               memcpy(&gtk_key->key[gtk_key_len], rx_mic, WILC_RX_MIC_KEY_LEN);
+
+       if (tx_mic)
+               memcpy(&gtk_key->key[gtk_key_len + WILC_RX_MIC_KEY_LEN],
+                      tx_mic, WILC_TX_MIC_KEY_LEN);
+
+       if (mode == WILC_AP_MODE) {
+               struct wid wid_list[2];
+
+               wid_list[0].id = WID_11I_MODE;
+               wid_list[0].type = WID_CHAR;
+               wid_list[0].size = sizeof(char);
+               wid_list[0].val = (s8 *)&cipher_mode;
+
+               wid_list[1].id = WID_ADD_RX_GTK;
+               wid_list[1].type = WID_STR;
+               wid_list[1].size = sizeof(*gtk_key) + t_key_len;
+               wid_list[1].val = (u8 *)gtk_key;
+
+               result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
+                                             ARRAY_SIZE(wid_list));
+               kfree(gtk_key);
+       } else if (mode == WILC_STATION_MODE) {
+               struct wid wid;
+
+               wid.id = WID_ADD_RX_GTK;
+               wid.type = WID_STR;
+               wid.size = sizeof(*gtk_key) + t_key_len;
+               wid.val = (u8 *)gtk_key;
+               result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+               kfree(gtk_key);
+       }
+
+       return result;
+}
+
+int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid)
+{
+       struct wid wid;
+
+       wid.id = WID_PMKID_INFO;
+       wid.type = WID_STR;
+       wid.size = (pmkid->numpmkid * sizeof(struct wilc_pmkid)) + 1;
+       wid.val = (u8 *)pmkid;
+
+       return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+}
+
+int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
+{
+       int result;
+       struct wid wid;
+
+       wid.id = WID_MAC_ADDR;
+       wid.type = WID_STR;
+       wid.size = ETH_ALEN;
+       wid.val = mac_addr;
+
+       result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
+       if (result)
+               netdev_err(vif->ndev, "Failed to get mac address\n");
+
+       return result;
+}
+
+int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr)
+{
+       struct wid wid;
+       int result;
+
+       wid.id = WID_MAC_ADDR;
+       wid.type = WID_STR;
+       wid.size = ETH_ALEN;
+       wid.val = mac_addr;
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev, "Failed to set mac address\n");
+
+       return result;
+}
+
+int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
+                     size_t ies_len)
+{
+       int result;
+       struct host_if_drv *hif_drv = vif->hif_drv;
+       struct wilc_conn_info *conn_info = &hif_drv->conn_info;
+
+       if (bssid)
+               ether_addr_copy(conn_info->bssid, bssid);
+
+       if (ies) {
+               conn_info->req_ies_len = ies_len;
+               conn_info->req_ies = kmemdup(ies, ies_len, GFP_KERNEL);
+               if (!conn_info->req_ies)
+                       return -ENOMEM;
+       }
+
+       result = wilc_send_connect_wid(vif);
+       if (result) {
+               PRINT_ER(vif->ndev, "Failed to send connect wid\n");
+               goto free_ies;
+       }
+
+#if KERNEL_VERSION(4, 15, 0) > LINUX_VERSION_CODE
+       hif_drv->connect_timer.data = (unsigned long)hif_drv;
+#endif
+       hif_drv->connect_timer_vif = vif;
+       mod_timer(&hif_drv->connect_timer,
+                 jiffies + msecs_to_jiffies(WILC_HIF_CONNECT_TIMEOUT_MS));
+
+       return 0;
+
+free_ies:
+       kfree(conn_info->req_ies);
+
+       return result;
+}
+
+int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
+{
+       struct wid wid;
+       int result;
+
+       wid.id = WID_CURRENT_CHANNEL;
+       wid.type = WID_CHAR;
+       wid.size = sizeof(char);
+       wid.val = &channel;
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev, "Failed to set channel\n");
+
+       return result;
+}
+
+int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode,
+                           u8 ifc_id)
+{
+       struct wid wid;
+       int result;
+       struct wilc_drv_handler drv;
+
+
+       wid.id = WID_SET_OPERATION_MODE;
+       wid.type = WID_STR;
+       wid.size = sizeof(drv);
+       wid.val = (u8 *)&drv;
+
+       drv.handler = cpu_to_le32(index);
+       drv.mode = (ifc_id | (mode << 1));
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev, "Failed to set driver handler\n");
+
+       return result;
+}
+
+s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val)
+{
+       struct wid wid;
+       s32 result;
+
+       wid.id = WID_SET_STA_MAC_INACTIVE_TIME;
+       wid.type = WID_STR;
+       wid.size = ETH_ALEN;
+       wid.val = kzalloc(wid.size, GFP_KERNEL);
+       if (!wid.val) {
+               PRINT_ER(vif->ndev, "Failed to allocate buffer\n");
+               return -ENOMEM;
+       }
+
+       ether_addr_copy(wid.val, mac);
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       kfree(wid.val);
+       if (result) {
+               PRINT_ER(vif->ndev, "Failed to set inactive mac\n");
+               return result;
+       }
+
+       wid.id = WID_GET_INACTIVE_TIME;
+       wid.type = WID_INT;
+       wid.val = (s8 *)out_val;
+       wid.size = sizeof(u32);
+       result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev, "Failed to get inactive time\n");
+
+       PRINT_INFO(vif->ndev, CFG80211_DBG, "Getting inactive time : %d\n",
+                  *out_val);
+
+       return result;
+}
+
+int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
+{
+       struct wid wid;
+       int result;
+
+       if (!rssi_level) {
+               PRINT_ER(vif->ndev, "RSS pointer value is null\n");
+               return -EFAULT;
+       }
+
+       wid.id = WID_RSSI;
+       wid.type = WID_CHAR;
+       wid.size = sizeof(char);
+       wid.val = rssi_level;
+       result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
+       if (result)
+               netdev_err(vif->ndev, "Failed to get RSSI value\n");
+
+       return result;
+}
+
+int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats)
+{
+       int result;
+       struct host_if_msg *msg;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG, " getting async statistics\n");
+       msg = wilc_alloc_work(vif, handle_get_statistics, false);
+       if (IS_ERR(msg))
+               return PTR_ERR(msg);
+
+       msg->body.data = (char *)stats;
+
+       result = wilc_enqueue_work(msg);
+       if (result) {
+               PRINT_ER(vif->ndev, "enqueue work failed\n");
+               kfree(msg);
+               return result;
+       }
+
+       return result;
+}
+
+int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *param)
+{
+       struct wid wid_list[4];
+       int i = 0;
+
+       if (param->flag & WILC_CFG_PARAM_RETRY_SHORT) {
+               wid_list[i].id = WID_SHORT_RETRY_LIMIT;
+               wid_list[i].val = (s8 *)&param->short_retry_limit;
+               wid_list[i].type = WID_SHORT;
+               wid_list[i].size = sizeof(u16);
+               i++;
+       }
+       if (param->flag & WILC_CFG_PARAM_RETRY_LONG) {
+               wid_list[i].id = WID_LONG_RETRY_LIMIT;
+               wid_list[i].val = (s8 *)&param->long_retry_limit;
+               wid_list[i].type = WID_SHORT;
+               wid_list[i].size = sizeof(u16);
+               i++;
+       }
+       if (param->flag & WILC_CFG_PARAM_FRAG_THRESHOLD) {
+               wid_list[i].id = WID_FRAG_THRESHOLD;
+               wid_list[i].val = (s8 *)&param->frag_threshold;
+               wid_list[i].type = WID_SHORT;
+               wid_list[i].size = sizeof(u16);
+               i++;
+       }
+       if (param->flag & WILC_CFG_PARAM_RTS_THRESHOLD) {
+               wid_list[i].id = WID_RTS_THRESHOLD;
+               wid_list[i].val = (s8 *)&param->rts_threshold;
+               wid_list[i].type = WID_SHORT;
+               wid_list[i].size = sizeof(u16);
+               i++;
+       }
+
+       return wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, i);
+}
+
+#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
+static void get_periodic_rssi(struct timer_list *t)
+#else
+static void get_periodic_rssi(unsigned long arg)
+#endif
+{
+#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
+       struct wilc_vif *vif = from_timer(vif, t, periodic_rssi);
+#else
+       struct wilc_vif *vif = (struct wilc_vif *)arg;
+#endif
+
+       if (!vif->hif_drv) {
+               PRINT_ER(vif->ndev, "hif driver is NULL\n");
+               return;
+       }
+
+       if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
+               wilc_get_stats_async(vif, &vif->periodic_stats);
+
+       mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
+}
+
+int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
+{
+       struct host_if_drv *hif_drv;
+       struct wilc_vif *vif = netdev_priv(dev);
+
+       hif_drv = kzalloc(sizeof(*hif_drv), GFP_KERNEL);
+       if (!hif_drv) {
+               PRINT_ER(dev, "hif driver is NULL\n");
+               return -ENOMEM;
+       }
+       *hif_drv_handler = hif_drv;
+       vif->hif_drv = hif_drv;
+
+#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
+       timer_setup(&hif_drv->scan_timer, timer_scan_cb, 0);
+       timer_setup(&hif_drv->connect_timer, timer_connect_cb, 0);
+       timer_setup(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0);
+       timer_setup(&vif->periodic_rssi, get_periodic_rssi, 0);
+#else
+       setup_timer(&hif_drv->scan_timer, timer_scan_cb, 0);
+       setup_timer(&hif_drv->connect_timer, timer_connect_cb, 0);
+       setup_timer(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0);
+       setup_timer(&vif->periodic_rssi, get_periodic_rssi,
+                           (unsigned long)vif);
+#endif
+       mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
+
+       hif_drv->hif_state = HOST_IF_IDLE;
+
+       hif_drv->p2p_timeout = 0;
+
+       return 0;
+}
+
+int wilc_deinit(struct wilc_vif *vif)
+{
+       int result = 0;
+       struct host_if_drv *hif_drv = vif->hif_drv;
+
+       if (!hif_drv) {
+               PRINT_ER(vif->ndev, "hif driver is NULL\n");
+               return -EFAULT;
+       }
+
+       mutex_lock(&vif->wilc->deinit_lock);
+
+       del_timer_sync(&hif_drv->scan_timer);
+       del_timer_sync(&hif_drv->connect_timer);
+       del_timer_sync(&vif->periodic_rssi);
+       del_timer_sync(&hif_drv->remain_on_ch_timer);
+
+       if (hif_drv->usr_scan_req.scan_result) {
+               hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL,
+                                                 hif_drv->usr_scan_req.arg);
+               hif_drv->usr_scan_req.scan_result = NULL;
+       }
+
+       hif_drv->hif_state = HOST_IF_IDLE;
+
+       kfree(hif_drv);
+       vif->hif_drv = NULL;
+
+       mutex_unlock(&vif->wilc->deinit_lock);
+       return result;
+}
+
+void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
+{
+       int result;
+       struct host_if_msg *msg;
+       int id;
+       struct host_if_drv *hif_drv;
+       struct wilc_vif *vif;
+       int srcu_idx;
+
+       id = get_unaligned_le32(&buffer[length - 4]);
+       srcu_idx = srcu_read_lock(&wilc->srcu);
+       vif = wilc_get_vif_from_idx(wilc, id);
+       if (!vif)
+               goto out;
+
+       hif_drv = vif->hif_drv;
+       if (!hif_drv) {
+               PRINT_ER(vif->ndev, "driver not init[%p]\n", hif_drv);
+               goto out;
+       }
+
+       msg = wilc_alloc_work(vif, handle_rcvd_ntwrk_info, false);
+       if (IS_ERR(msg))
+               goto out;
+
+       msg->body.net_info.frame_len = get_unaligned_le16(&buffer[6]) - 1;
+       msg->body.net_info.rssi = buffer[8];
+       msg->body.net_info.mgmt = kmemdup(&buffer[9],
+                                         msg->body.net_info.frame_len,
+                                         GFP_KERNEL);
+       if (!msg->body.net_info.mgmt) {
+               kfree(msg);
+               goto out;
+       }
+
+       result = wilc_enqueue_work(msg);
+       if (result) {
+               PRINT_ER(vif->ndev, "message parameters (%d)\n", result);
+               kfree(msg->body.net_info.mgmt);
+               kfree(msg);
+       }
+out:
+       srcu_read_unlock(&wilc->srcu, srcu_idx);
+}
+
+void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length)
+{
+       int result;
+       struct host_if_msg *msg;
+       int id;
+       struct host_if_drv *hif_drv;
+       struct wilc_vif *vif;
+       int srcu_idx;
+
+       mutex_lock(&wilc->deinit_lock);
+
+       id = get_unaligned_le32(&buffer[length - 4]);
+       srcu_idx = srcu_read_lock(&wilc->srcu);
+       vif = wilc_get_vif_from_idx(wilc, id);
+       if (!vif)
+               goto out;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                  "General asynchronous info packet received\n");
+
+       hif_drv = vif->hif_drv;
+
+       if (!hif_drv) {
+               PRINT_ER(vif->ndev, "hif driver is NULL\n");
+               goto out;
+       }
+
+       if (!hif_drv->conn_info.conn_result) {
+               PRINT_ER(vif->ndev, "there is no current Connect Request\n");
+               goto out;
+       }
+
+       msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false);
+       if (IS_ERR(msg))
+               goto out;
+
+       msg->body.mac_info.status = buffer[7];
+       PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                  "Received MAC status= %d Reason= %d Info = %d\n",
+                  buffer[7], buffer[8], buffer[9]);
+       result = wilc_enqueue_work(msg);
+       if (result) {
+               PRINT_ER(vif->ndev, "enqueue work failed\n");
+               kfree(msg);
+       }
+out:
+       mutex_unlock(&wilc->deinit_lock);
+       srcu_read_unlock(&wilc->srcu, srcu_idx);
+}
+
+void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
+{
+       int result;
+       int id;
+       struct host_if_drv *hif_drv;
+       struct wilc_vif *vif;
+       int srcu_idx;
+
+       id = get_unaligned_le32(&buffer[length - 4]);
+       srcu_idx = srcu_read_lock(&wilc->srcu);
+       vif = wilc_get_vif_from_idx(wilc, id);
+       if (!vif)
+               goto out;
+
+       PRINT_INFO(vif->ndev, GENERIC_DBG, "Scan notification received\n");
+
+       hif_drv = vif->hif_drv;
+       if (!hif_drv) {
+               PRINT_ER(vif->ndev, "hif driver is NULL\n");
+               goto out;
+       }
+
+       if (hif_drv->usr_scan_req.scan_result) {
+               struct host_if_msg *msg;
+
+               msg = wilc_alloc_work(vif, handle_scan_complete, false);
+               if (IS_ERR(msg))
+                       goto out;
+
+               result = wilc_enqueue_work(msg);
+               if (result) {
+                       PRINT_ER(vif->ndev, "enqueue work failed\n");
+                       kfree(msg);
+               }
+       }
+out:
+       srcu_read_unlock(&wilc->srcu, srcu_idx);
+}
+
+int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie,
+                          u32 duration, u16 chan,
+                          void (*expired)(void *, u64), void *user_arg)
+{
+       struct wilc_remain_ch roc;
+       int result;
+
+       PRINT_INFO(vif->ndev, CFG80211_DBG, "called\n");
+       roc.ch = chan;
+       roc.expired = expired;
+       roc.arg = user_arg;
+       roc.duration = duration;
+       roc.cookie = cookie;
+       result = handle_remain_on_chan(vif, &roc);
+       if (result)
+               PRINT_ER(vif->ndev, "failed to set remain on channel\n");
+
+       return result;
+}
+
+int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie)
+{
+       int result;
+       struct host_if_drv *hif_drv = vif->hif_drv;
+
+       if (!hif_drv) {
+               PRINT_ER(vif->ndev, "hif driver is NULL\n");
+               return -EFAULT;
+       }
+
+       del_timer(&hif_drv->remain_on_ch_timer);
+
+       result = handle_roc_expired(vif, cookie);
+
+       return result;
+}
+
+void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
+{
+       struct wid wid;
+       int result;
+       struct wilc_reg_frame reg_frame;
+
+       wid.id = WID_REGISTER_FRAME;
+       wid.type = WID_STR;
+       wid.size = sizeof(reg_frame);
+       wid.val = (u8 *)&reg_frame;
+
+       memset(&reg_frame, 0x0, sizeof(reg_frame));
+       reg_frame.reg = reg;
+
+       switch (frame_type) {
+       case IEEE80211_STYPE_ACTION:
+               PRINT_INFO(vif->ndev, HOSTINF_DBG, "ACTION\n");
+               reg_frame.reg_id = WILC_FW_ACTION_FRM_IDX;
+               break;
+
+       case IEEE80211_STYPE_PROBE_REQ:
+               PRINT_INFO(vif->ndev, HOSTINF_DBG, "PROBE REQ\n");
+               reg_frame.reg_id = WILC_FW_PROBE_REQ_IDX;
+               break;
+
+       default:
+               PRINT_INFO(vif->ndev, HOSTINF_DBG, "Not valid frame type\n");
+               break;
+       }
+       reg_frame.frame_type = cpu_to_le16(frame_type);
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev, "Failed to frame register\n");
+}
+
+int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
+                   struct cfg80211_beacon_data *params)
+{
+       struct wid wid;
+       int result;
+       u8 *cur_byte;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                  "Setting adding beacon\n");
+
+       wid.id = WID_ADD_BEACON;
+       wid.type = WID_BIN;
+       wid.size = params->head_len + params->tail_len + 16;
+       wid.val = kzalloc(wid.size, GFP_KERNEL);
+       if (!wid.val) {
+               PRINT_ER(vif->ndev, "Failed to allocate buffer\n");
+               return -ENOMEM;
+       }
+
+       cur_byte = wid.val;
+       put_unaligned_le32(interval, cur_byte);
+       cur_byte += 4;
+       put_unaligned_le32(dtim_period, cur_byte);
+       cur_byte += 4;
+       put_unaligned_le32(params->head_len, cur_byte);
+       cur_byte += 4;
+
+       if (params->head_len > 0)
+               memcpy(cur_byte, params->head, params->head_len);
+       cur_byte += params->head_len;
+
+       put_unaligned_le32(params->tail_len, cur_byte);
+       cur_byte += 4;
+
+       if (params->tail_len > 0)
+               memcpy(cur_byte, params->tail, params->tail_len);
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev, "Failed to send add beacon\n");
+
+       kfree(wid.val);
+
+       return result;
+}
+
+int wilc_del_beacon(struct wilc_vif *vif)
+{
+       int result;
+       struct wid wid;
+       u8 del_beacon = 0;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                  "Setting deleting beacon message queue params\n");
+
+       wid.id = WID_DEL_BEACON;
+       wid.type = WID_CHAR;
+       wid.size = sizeof(char);
+       wid.val = &del_beacon;
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev, "Failed to send delete beacon\n");
+
+       return result;
+}
+
+int wilc_add_station(struct wilc_vif *vif, const u8 *mac,
+                    struct station_parameters *params)
+{
+       struct wid wid;
+       int result;
+       u8 *cur_byte;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                  "Setting adding station message queue params\n");
+
+       wid.id = WID_ADD_STA;
+       wid.type = WID_BIN;
+       wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len;
+       wid.val = kmalloc(wid.size, GFP_KERNEL);
+       if (!wid.val)
+               return -ENOMEM;
+
+       cur_byte = wid.val;
+       wilc_hif_pack_sta_param(vif, cur_byte, mac, params);
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result != 0)
+               PRINT_ER(vif->ndev, "Failed to send add station\n");
+
+       kfree(wid.val);
+
+       return result;
+}
+
+int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr)
+{
+       struct wid wid;
+       int result;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                  "Setting deleting station message queue params\n");
+
+       wid.id = WID_REMOVE_STA;
+       wid.type = WID_BIN;
+       wid.size = ETH_ALEN;
+       wid.val = kzalloc(wid.size, GFP_KERNEL);
+       if (!wid.val) {
+               PRINT_ER(vif->ndev, "Failed to allocate buffer\n");
+               return -ENOMEM;
+       }
+
+       if (!mac_addr)
+               eth_broadcast_addr(wid.val);
+       else
+               ether_addr_copy(wid.val, mac_addr);
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev, "Failed to del station\n");
+
+       kfree(wid.val);
+
+       return result;
+}
+
+int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN])
+{
+       struct wid wid;
+       int result;
+       int i;
+       u8 assoc_sta = 0;
+       struct wilc_del_all_sta del_sta;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                  "Setting deauthenticating station message queue params\n");
+       memset(&del_sta, 0x0, sizeof(del_sta));
+       for (i = 0; i < WILC_MAX_NUM_STA; i++) {
+               if (!is_zero_ether_addr(mac_addr[i])) {
+                       PRINT_INFO(vif->ndev,
+                                  CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n",
+                                  mac_addr[i][0], mac_addr[i][1],
+                                  mac_addr[i][2], mac_addr[i][3],
+                                  mac_addr[i][4], mac_addr[i][5]);
+                       assoc_sta++;
+                       ether_addr_copy(del_sta.mac[i], mac_addr[i]);
+               }
+       }
+       if (!assoc_sta) {
+               PRINT_INFO(vif->ndev, CFG80211_DBG, "NO ASSOCIATED STAS\n");
+               return 0;
+       }
+       del_sta.assoc_sta = assoc_sta;
+
+       wid.id = WID_DEL_ALL_STA;
+       wid.type = WID_STR;
+       wid.size = (assoc_sta * ETH_ALEN) + 1;
+       wid.val = (u8 *)&del_sta;
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev, "Failed to send delete all station\n");
+
+       return result;
+}
+
+int wilc_edit_station(struct wilc_vif *vif, const u8 *mac,
+                     struct station_parameters *params)
+{
+       struct wid wid;
+       int result;
+       u8 *cur_byte;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                  "Setting editing station message queue params\n");
+
+       wid.id = WID_EDIT_STA;
+       wid.type = WID_BIN;
+       wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len;
+       wid.val = kmalloc(wid.size, GFP_KERNEL);
+       if (!wid.val)
+               return -ENOMEM;
+
+       cur_byte = wid.val;
+       wilc_hif_pack_sta_param(vif, cur_byte, mac, params);
+
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev, "Failed to send edit station\n");
+
+       kfree(wid.val);
+       return result;
+}
+
+int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
+{
+       struct wid wid;
+       int result;
+       s8 power_mode;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG, "\n\n>> Setting PS to %d <<\n\n",
+                  enabled);
+       if (enabled)
+               power_mode = WILC_FW_MIN_FAST_PS;
+       else
+               power_mode = WILC_FW_NO_POWERSAVE;
+
+       wid.id = WID_POWER_MANAGEMENT;
+       wid.val = &power_mode;
+       wid.size = sizeof(char);
+       result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (result)
+               PRINT_ER(vif->ndev, "Failed to send power management\n");
+
+       return result;
+}
+
+int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count,
+                               u8 *mc_list)
+{
+       int result;
+       struct host_if_msg *msg;
+
+       PRINT_INFO(vif->ndev, HOSTINF_DBG,
+                  "Setting Multicast Filter params\n");
+       msg = wilc_alloc_work(vif, handle_set_mcast_filter, false);
+       if (IS_ERR(msg))
+               return PTR_ERR(msg);
+
+       msg->body.mc_info.enabled = enabled;
+       msg->body.mc_info.cnt = count;
+       msg->body.mc_info.mc_list = mc_list;
+
+       result = wilc_enqueue_work(msg);
+       if (result) {
+               PRINT_ER(vif->ndev, "enqueue work failed\n");
+               kfree(msg);
+       }
+       return result;
+}
+
+int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
+{
+       struct wid wid;
+
+       wid.id = WID_TX_POWER;
+       wid.type = WID_CHAR;
+       wid.val = &tx_power;
+       wid.size = sizeof(char);
+
+       return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+}
+
+int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
+{
+       struct wid wid;
+
+       wid.id = WID_TX_POWER;
+       wid.type = WID_CHAR;
+       wid.val = tx_power;
+       wid.size = sizeof(char);
+
+       return wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
+}
+
+bool is_valid_gpio(struct wilc_vif *vif, u8 gpio)
+{
+       switch (vif->wilc->chip) {
+       case WILC_1000:
+               if (gpio == 0 || gpio == 1 || gpio == 4 || gpio == 6)
+                       return true;
+               else
+                       return false;
+       case WILC_3000:
+               if (gpio == 0 || gpio == 3 || gpio == 4 ||
+                   (gpio >= 17 && gpio <= 20))
+                       return true;
+               else
+                       return false;
+       default:
+               return false;
+       }
+}
+
+int wilc_set_antenna(struct wilc_vif *vif, u8 mode)
+{
+       struct wid wid;
+       int ret;
+       struct sysfs_attr_group *attr_syfs_p = &vif->wilc->attr_sysfs;
+       struct host_if_set_ant set_ant;
+
+       set_ant.mode = mode;
+
+       if (attr_syfs_p->ant_swtch_mode == ANT_SWTCH_INVALID_GPIO_CTRL) {
+               PRINT_ER(vif->ndev, "Ant switch GPIO mode is invalid.\n");
+               PRINT_ER(vif->ndev, "Set it using /sys/wilc/ant_swtch_mode\n");
+               return WILC_FAIL;
+       }
+
+       if (is_valid_gpio(vif, attr_syfs_p->antenna1)) {
+               set_ant.antenna1 = attr_syfs_p->antenna1;
+       } else {
+               PRINT_ER(vif->ndev, "Invalid GPIO %d\n", attr_syfs_p->antenna1);
+               return WILC_FAIL;
+       }
+
+       if (attr_syfs_p->ant_swtch_mode == ANT_SWTCH_DUAL_GPIO_CTRL) {
+               if ((attr_syfs_p->antenna2 != attr_syfs_p->antenna1) &&
+                   is_valid_gpio(vif, attr_syfs_p->antenna2)) {
+                       set_ant.antenna2 = attr_syfs_p->antenna2;
+               } else {
+                       PRINT_ER(vif->ndev, "Invalid GPIO %d\n",
+                                attr_syfs_p->antenna2);
+                       return WILC_FAIL;
+               }
+       }
+
+       set_ant.gpio_mode = attr_syfs_p->ant_swtch_mode;
+
+       wid.id = WID_ANTENNA_SELECTION;
+       wid.type = WID_BIN;
+       wid.val = (u8 *)&set_ant;
+       wid.size = sizeof(struct host_if_set_ant);
+       if (attr_syfs_p->ant_swtch_mode == ANT_SWTCH_SNGL_GPIO_CTRL)
+               PRINT_INFO(vif->ndev, CFG80211_DBG,
+                          "set antenna %d on GPIO %d\n", set_ant.mode,
+                          set_ant.antenna1);
+       else if (attr_syfs_p->ant_swtch_mode == ANT_SWTCH_DUAL_GPIO_CTRL)
+               PRINT_INFO(vif->ndev, CFG80211_DBG,
+                          "set antenna %d on GPIOs %d and %d\n",
+                          set_ant.mode, set_ant.antenna1,
+                          set_ant.antenna2);
+
+       ret = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
+       if (ret)
+               PRINT_ER(vif->ndev, "Failed to set antenna mode\n");
+
+       return ret;
+}
diff --git a/drivers/net/wireless/mchp/wilc_hif.h b/drivers/net/wireless/mchp/wilc_hif.h
new file mode 100644 (file)
index 0000000..5210975
--- /dev/null
@@ -0,0 +1,258 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
+ * All rights reserved.
+ */
+
+#ifndef HOST_INT_H
+#define HOST_INT_H
+#include <linux/ieee80211.h>
+#include "wilc_wlan_if.h"
+
+enum {
+       WILC_IDLE_MODE = 0x0,
+       WILC_AP_MODE = 0x1,
+       WILC_STATION_MODE = 0x2,
+       WILC_GO_MODE = 0x3,
+       WILC_CLIENT_MODE = 0x4,
+       WILC_MONITOR_MODE = 0x5
+};
+
+#define WILC_MAX_NUM_STA                       9
+#define WILC_MAX_NUM_SCANNED_CH                        14
+#define WILC_MAX_NUM_PROBED_SSID               10
+
+#define WILC_TX_MIC_KEY_LEN                    8
+#define WILC_RX_MIC_KEY_LEN                    8
+
+#define WILC_MAX_NUM_PMKIDS                    16
+#define WILC_ADD_STA_LENGTH                    40
+#define WILC_NUM_CONCURRENT_IFC                        2
+
+enum {
+       WILC_SET_CFG = 0,
+       WILC_GET_CFG
+};
+
+#define WILC_MAX_ASSOC_RESP_FRAME_SIZE   256
+extern uint32_t cfg_packet_timeout;
+
+struct assoc_resp {
+       __le16 capab_info;
+       __le16 status_code;
+       __le16 aid;
+} __packed;
+
+struct rf_info {
+       u8 link_speed;
+       s8 rssi;
+       u32 tx_cnt;
+       u32 rx_cnt;
+       u32 tx_fail_cnt;
+};
+
+enum host_if_state {
+       HOST_IF_IDLE                    = 0,
+       HOST_IF_SCANNING                = 1,
+       HOST_IF_CONNECTING              = 2,
+       HOST_IF_WAITING_CONN_RESP       = 3,
+       HOST_IF_CONNECTED               = 4,
+       HOST_IF_P2P_LISTEN              = 5,
+       HOST_IF_FORCE_32BIT             = 0xFFFFFFFF
+};
+
+struct wilc_pmkid {
+       u8 bssid[ETH_ALEN];
+       u8 pmkid[WLAN_PMKID_LEN];
+} __packed;
+
+struct wilc_pmkid_attr {
+       u8 numpmkid;
+       struct wilc_pmkid pmkidlist[WILC_MAX_NUM_PMKIDS];
+} __packed;
+
+struct cfg_param_attr {
+       u32 flag;
+       u16 short_retry_limit;
+       u16 long_retry_limit;
+       u16 frag_threshold;
+       u16 rts_threshold;
+};
+
+enum cfg_param {
+       WILC_CFG_PARAM_RETRY_SHORT = BIT(0),
+       WILC_CFG_PARAM_RETRY_LONG = BIT(1),
+       WILC_CFG_PARAM_FRAG_THRESHOLD = BIT(2),
+       WILC_CFG_PARAM_RTS_THRESHOLD = BIT(3)
+};
+
+enum scan_event {
+       SCAN_EVENT_NETWORK_FOUND        = 0,
+       SCAN_EVENT_DONE                 = 1,
+       SCAN_EVENT_ABORTED              = 2,
+       SCAN_EVENT_FORCE_32BIT          = 0xFFFFFFFF
+};
+
+enum conn_event {
+       EVENT_CONN_RESP         = 0,
+       EVENT_DISCONN_NOTIF     = 1,
+       EVENT_FORCE_32BIT               = 0xFFFFFFFF
+};
+
+enum {
+       WILC_HIF_SDIO = 0,
+       WILC_HIF_SPI = BIT(0),
+       WILC_HIF_SDIO_GPIO_IRQ = BIT(1)
+};
+
+enum {
+       WILC_MAC_STATUS_INIT = -1,
+       WILC_MAC_STATUS_DISCONNECTED = 0,
+       WILC_MAC_STATUS_CONNECTED = 1
+};
+
+struct wilc_rcvd_net_info {
+       s8 rssi;
+       u8 ch;
+       u16 frame_len;
+       struct ieee80211_mgmt *mgmt;
+};
+
+typedef void (*wilc_remain_on_chan_ready)(void *);
+
+struct wilc_user_scan_req {
+       void (*scan_result)(enum scan_event evt,
+                           struct wilc_rcvd_net_info *info, void *priv);
+       void *arg;
+       u32 ch_cnt;
+};
+
+struct wilc_conn_info {
+       u8 bssid[ETH_ALEN];
+       u8 security;
+       enum authtype auth_type;
+       u8 ch;
+       u8 *req_ies;
+       size_t req_ies_len;
+       u8 *resp_ies;
+       u16 resp_ies_len;
+       u16 status;
+       void (*conn_result)(enum conn_event evt, u8 status, void *priv);
+       void *arg;
+       void *param;
+};
+
+struct wilc_remain_ch {
+       u16 ch;
+       u32 duration;
+       void (*expired)(void *priv, u64 cookie);
+       void *arg;
+       u64 cookie;
+};
+
+struct host_if_drv {
+       struct wilc_user_scan_req usr_scan_req;
+       struct wilc_conn_info conn_info;
+       struct wilc_remain_ch remain_on_ch;
+       u64 p2p_timeout;
+
+       enum host_if_state hif_state;
+
+       u8 assoc_bssid[ETH_ALEN];
+       struct completion comp_test_key_block;
+       struct completion comp_test_disconn_block;
+       struct completion comp_get_rssi;
+       struct completion comp_inactive_time;
+
+       struct timer_list scan_timer;
+       struct wilc_vif *scan_timer_vif;
+
+       struct timer_list connect_timer;
+       struct wilc_vif *connect_timer_vif;
+
+       struct timer_list remain_on_ch_timer;
+       struct wilc_vif *remain_on_ch_timer_vif;
+
+       bool ifc_up;
+       u8 assoc_resp[WILC_MAX_ASSOC_RESP_FRAME_SIZE];
+};
+
+struct wilc_vif;
+
+signed int wilc_send_buffered_eap(struct wilc_vif *vif,
+                                 void (*deliver_to_stack)(struct wilc_vif *,
+                                                          u8 *, u32, u32, u8),
+                                 void (*eap_buf_param)(void *), u8 *buff,
+                                 unsigned int size, unsigned int pkt_offset,
+                                 void *user_arg);
+int wilc_remove_wep_key(struct wilc_vif *vif, u8 index);
+int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index);
+int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
+                            u8 index);
+int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
+                           u8 index, u8 mode, enum authtype auth_type);
+int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
+                const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
+                u8 mode, u8 cipher_mode, u8 index);
+s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac,
+                          u32 *out_val);
+int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
+                   u8 index, u32 key_rsc_len, const u8 *key_rsc,
+                   const u8 *rx_mic, const u8 *tx_mic, u8 mode,
+                   u8 cipher_mode);
+int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid);
+int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr);
+int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr);
+int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
+                     size_t ies_len);
+int wilc_disconnect(struct wilc_vif *vif);
+int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel);
+int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level);
+int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
+             u8 *ch_freq_list, u8 ch_list_len,
+             void (*scan_result_fn)(enum scan_event,
+                                    struct wilc_rcvd_net_info *, void *),
+             void *user_arg, struct cfg80211_scan_request *request);
+int wilc_hif_set_cfg(struct wilc_vif *vif,
+                    struct cfg_param_attr *cfg_param);
+int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler);
+int wilc_deinit(struct wilc_vif *vif);
+int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
+                   struct cfg80211_beacon_data *params);
+int wilc_del_beacon(struct wilc_vif *vif);
+int wilc_add_station(struct wilc_vif *vif, const u8 *mac,
+                    struct station_parameters *params);
+int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]);
+int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr);
+int wilc_edit_station(struct wilc_vif *vif, const u8 *mac,
+                     struct station_parameters *params);
+int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout);
+int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count,
+                               u8 *mc_list);
+int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie,
+                          u32 duration, u16 chan,
+                          void (*expired)(void *, u64), void *user_arg);
+int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie);
+void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg);
+int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode,
+                           u8 ifc_id);
+int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats);
+int wilc_get_vif_idx(struct wilc_vif *vif);
+int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power);
+int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power);
+/*0 select antenna 1 , 2 select antenna mode , 2 allow the firmware to choose
+ * the best antenna
+ */
+int wilc_set_antenna(struct wilc_vif *vif, u8 mode);
+
+void wilc_set_wowlan_trigger(struct wilc_vif *vif, u8 wowlan_trigger);
+
+extern u8 wilc_initialized;
+s32 handle_scan_done(struct wilc_vif *vif, enum scan_event evt);
+void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length);
+void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length);
+void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length);
+void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
+                               struct cfg80211_crypto_settings *crypto);
+void handle_connect_cancel(struct wilc_vif *vif);
+#endif
index 8a2a0b7..98c9750 100644 (file)
@@ -29,22 +29,14 @@ void wilc_wfi_handle_monitor_rx(struct wilc *wilc, u8 *buff, u32 size)
        struct wilc_vif *vif = 0;
        struct sk_buff *skb = NULL;
        struct wfi_rtap_hdr *hdr;
-       int i;
-
-       for (i = 0; i < wilc->vif_num; i++) {
-               if (wilc->vif[i]->iftype == WILC_MONITOR_MODE) {
-                       vif = wilc->vif[i];
-                       break;
-               }
-       }
 
+       vif = wilc_get_vif_from_type(wilc, WILC_MONITOR_MODE);
        if (!vif) {
                PRINT_D(vif->ndev, HOSTAPD_DBG, "Monitor interface not up\n");
                return;
        }
 
        skb = dev_alloc_skb(size + sizeof(*hdr));
-
        if (!skb) {
                PRINT_D(vif->ndev, HOSTAPD_DBG,
                        "Monitor if: No memory to allocate skb");
@@ -93,8 +85,7 @@ void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size)
        }
 
        /* Get WILC header */
-       memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
-       le32_to_cpus(&header);
+       header = get_unaligned_le32(buff - HOST_HDR_OFFSET);
        /*
         * The packet offset field contain info about what type of management
         * the frame we are dealing with and ack status
@@ -302,7 +293,11 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
        strncpy(wl->monitor_dev->name, name, IFNAMSIZ);
        wl->monitor_dev->name[IFNAMSIZ - 1] = 0;
        wl->monitor_dev->netdev_ops = &wilc_wfi_netdev_ops;
-
+#if KERNEL_VERSION(4, 11, 9) <= LINUX_VERSION_CODE
+       wl->monitor_dev->needs_free_netdev = true;
+#else
+       wl->monitor_dev->destructor = free_netdev;
+#endif
        if (register_netdevice(wl->monitor_dev)) {
                PRINT_ER(real_dev, "register_netdevice failed\n");
                return NULL;
@@ -318,7 +313,7 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
        return wl->monitor_dev;
 }
 
-void wilc_wfi_deinit_mon_interface(struct wilc *wl)
+void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked)
 {
        if (!wl->monitor_dev)
                return;
@@ -326,8 +321,10 @@ void wilc_wfi_deinit_mon_interface(struct wilc *wl)
        PRINT_INFO(wl->monitor_dev, HOSTAPD_DBG,
                   "In Deinit monitor interface\n");
        PRINT_INFO(wl->monitor_dev, HOSTAPD_DBG, "Unregister monitor netdev\n");
-       unregister_netdev(wl->monitor_dev);
-       free_netdev(wl->monitor_dev);
+       if (rtnl_locked)
+               unregister_netdevice(wl->monitor_dev);
+       else
+               unregister_netdev(wl->monitor_dev);
        PRINT_INFO(wl->monitor_dev, HOSTAPD_DBG,
                   "Deinit monitor interface done\n");
        wl->monitor_dev = NULL;
index 5f769fa..9c95f2c 100644 (file)
 #include <linux/interrupt.h>
 #include <net/ip.h>
 #include <linux/module.h>
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-#include <linux/inetdevice.h>
-#endif /* DISABLE_PWRSAVE_AND_SCAN_DURING_IP */
 
 #include "wilc_netdev.h"
 #include "wilc_wfi_cfgoperations.h"
 
 #define WILC_MULTICAST_TABLE_SIZE      8
 
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-bool g_ignore_PS_state;
-#define WILC_IP_TIMEOUT_MS             15000
-
-void handle_pwrsave_for_IP(struct wilc_vif *vif, uint8_t state)
-{
-       struct wilc_priv *priv;
-
-       priv = wdev_priv(vif->ndev->ieee80211_ptr);
-
-       switch (state) {
-       case IP_STATE_OBTAINING:
-
-               PRINT_INFO(vif->ndev, GENERIC_DBG,
-                          "Obtaining IP, Disable (Scan-Set PowerSave)\n");
-               PRINT_INFO(vif->ndev, GENERIC_DBG,
-                          "Save the Current state of the PS = %d\n",
-                          vif->pwrsave_current_state);
-
-               vif->obtaining_ip = true;
-
-               /* Set this flag to avoid storing the disabled case of PS which
-                * occurs duringIP
-                */
-               g_ignore_PS_state = true;
-
-               wilc_set_power_mgmt(vif, 0, 0);
-
-               /* Start the DuringIPTimer */
-       #if KERNEL_VERSION(4, 15, 0) > LINUX_VERSION_CODE
-               vif->during_ip_timer.data = (uint32_t)vif;
-       #endif
-               mod_timer(&vif->during_ip_timer,
-                         (jiffies + msecs_to_jiffies(20000)));
-
-               break;
-
-       case IP_STATE_OBTAINED:
-
-               PRINT_INFO(vif->ndev, GENERIC_DBG,
-                          "IP obtained , Enable (Scan-Set PowerSave)\n");
-               PRINT_INFO(vif->ndev, GENERIC_DBG,
-                          "Recover the state of the PS = %d\n",
-                          vif->pwrsave_current_state);
-
-               vif->obtaining_ip = false;
-
-               wilc_set_power_mgmt(vif, vif->pwrsave_current_state, 0);
-
-               del_timer(&vif->during_ip_timer);
-
-               break;
-
-       case IP_STATE_GO_ASSIGNING:
-
-               vif->obtaining_ip = true;
-
-               /* Start the DuringIPTimer */
-       #if KERNEL_VERSION(4, 15, 0) > LINUX_VERSION_CODE
-               vif->during_ip_timer.data = (uint32_t)vif;
-       #endif
-               mod_timer(&vif->during_ip_timer,
-                         (jiffies + msecs_to_jiffies(WILC_IP_TIMEOUT_MS)));
-
-               break;
-
-       default: //IP_STATE_DEFAULT
-
-               vif->obtaining_ip = false;
-
-               /* Stop the DuringIPTimer */
-               del_timer(&vif->during_ip_timer);
-
-               break;
-       }
-}
-
-void store_power_save_current_state(struct wilc_vif *vif, bool val)
-{
-       if (g_ignore_PS_state) {
-               g_ignore_PS_state = false;
-               return;
-       }
-       vif->pwrsave_current_state = val;
-}
-
-#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
-void clear_during_ip(struct timer_list *t)
-#else
-void clear_during_ip(unsigned long arg)
-#endif
-{
-#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
-       struct wilc_vif *vif = from_timer(vif, t, during_ip_timer);
-#else
-       struct wilc_vif *vif = (struct wilc_vif *)arg;
-#endif
-
-       PRINT_ER(vif->ndev, "Unable to Obtain IP\n");
-
-       vif->obtaining_ip = false;
-
-       wilc_powersave_state_changes(vif);
-}
-#endif /* DISABLE_PWRSAVE_AND_SCAN_DURING_IP */
-
 static int wilc_mac_open(struct net_device *ndev);
 static int wilc_mac_close(struct net_device *ndev);
 
@@ -136,24 +27,17 @@ int recovery_on;
 int wait_for_recovery;
 static int debug_thread(void *arg)
 {
-       struct net_device *dev = arg;
-       struct wilc_vif *vif = netdev_priv(dev);
-       struct wilc *wl;
-       struct wilc_priv *priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy);
+       struct wilc *wl = arg;
+       struct wilc_vif *vif;
        signed long timeout;
-       struct host_if_drv *hif_drv = (struct host_if_drv *)priv->hif_drv;
+       struct host_if_drv *hif_drv;
        int i = 0;
 
-       if (!vif)
-               return -1;
-
-       wl = vif->wilc;
-       if (!wl)
-               return -1;
-
        complete(&wl->debug_thread_started);
 
        while (1) {
+               int srcu_idx;
+
                if (!wl->initialized && !kthread_should_stop()) {
                        msleep(1000);
                        continue;
@@ -165,64 +49,76 @@ static int debug_thread(void *arg)
                                                msecs_to_jiffies(6000))) {
                        while (!kthread_should_stop())
                                schedule();
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "Exit debug thread\n");
+                       pr_info("Exit debug thread\n");
                        return 0;
                }
-
                if (!debug_running)
                        continue;
-               PRINT_INFO(dev, GENERIC_DBG,
-                          "*** Debug Thread Running ***\n");
+
+               pr_debug("%s *** Debug Thread Running ***cnt[%d]\n", __func__,
+                        cfg_packet_timeout);
+
                if (cfg_packet_timeout < 5)
                        continue;
 
-               PRINT_INFO(dev, GENERIC_DBG,
-                          "<Recover>\n");
+               pr_info("%s <Recover>\n", __func__);
                cfg_packet_timeout = 0;
                timeout = 10;
                recovery_on = 1;
                wait_for_recovery = 1;
-               for (i = 0; i < WILC_NUM_CONCURRENT_IFC; i++)
-                       wilc_mac_close(wl->vif[i]->ndev);
-               for (i = WILC_NUM_CONCURRENT_IFC; i > 0; i--) {
-                       while (wilc_mac_open(wl->vif[i-1]->ndev) && --timeout)
+
+               srcu_idx = srcu_read_lock(&wl->srcu);
+               list_for_each_entry_rcu(vif, &wl->vif_list, list) {
+                       //close the interface only if it was open
+                       if (vif->mac_opened) {
+                               wilc_mac_close(vif->ndev);
+                               vif->restart = 1;
+                       }
+               }
+               //TODO://Need to find way to call them in reverse
+               i = 0;
+               list_for_each_entry_rcu(vif, &wl->vif_list, list) {
+                       struct wilc_conn_info *info;
+
+                       // Only open the interface manually closed earlier
+                       if (!vif->restart)
+                               continue;
+                       i++;
+                       hif_drv = vif->priv.hif_drv;
+                       while (wilc_mac_open(vif->ndev) && --timeout)
                                msleep(100);
 
                        if (timeout == 0)
                                PRINT_WRN(vif->ndev, GENERIC_DBG,
                                          "Couldn't restart ifc %d\n", i);
-               }
-               if (hif_drv->hif_state == HOST_IF_CONNECTED) {
-                       struct wilc_conn_info *conn_info = &hif_drv->conn_info;
 
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "notify the user with the Disconnection\n");
-                       if (hif_drv->usr_scan_req.scan_result) {
+                       if (hif_drv->hif_state == HOST_IF_CONNECTED) {
+                               info = &hif_drv->conn_info;
                                PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                          "Abort the running OBSS Scan\n");
-                               del_timer(&hif_drv->scan_timer);
-                               handle_scan_done(vif, SCAN_EVENT_ABORTED);
-                       }
-                       if (conn_info->conn_result) {
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-
-                               handle_pwrsave_for_IP(vif, IP_STATE_DEFAULT);
-#endif
-
-                               conn_info->conn_result(EVENT_DISCONN_NOTIF,
-                                                      0, conn_info->arg);
-                       } else {
-                               PRINT_ER(vif->ndev, "Connect result NULL\n");
+                                          "notify the user with the Disconnection\n");
+                               if (hif_drv->usr_scan_req.scan_result) {
+                                       PRINT_INFO(vif->ndev, GENERIC_DBG,
+                                                  "Abort the running OBSS Scan\n");
+                                       del_timer(&hif_drv->scan_timer);
+                                       handle_scan_done(vif,
+                                                        SCAN_EVENT_ABORTED);
+                               }
+                               if (info->conn_result) {
+                                       info->conn_result(EVENT_DISCONN_NOTIF,
+                                                         0, info->arg);
+                               } else {
+                                       PRINT_ER(vif->ndev,
+                                                "Connect result NULL\n");
+                               }
+                               eth_zero_addr(hif_drv->assoc_bssid);
+                               info->req_ies_len = 0;
+                               kfree(info->req_ies);
+                               info->req_ies = NULL;
+                               hif_drv->hif_state = HOST_IF_IDLE;
                        }
-                       eth_zero_addr(hif_drv->assoc_bssid);
-
-                       conn_info->req_ies_len = 0;
-                       kfree(conn_info->req_ies);
-                       conn_info->req_ies = NULL;
-
-                       hif_drv->hif_state = HOST_IF_IDLE;
+                       vif->restart = 0;
                }
+               srcu_read_unlock(&wl->srcu, srcu_idx);
                recovery_on = 0;
        }
        return 0;
@@ -231,10 +127,10 @@ static int debug_thread(void *arg)
 void wilc_disable_irq(struct wilc *wilc, int wait)
 {
        if (wait) {
-               PRINT_INFO(wilc->vif[0]->ndev, INT_DBG, "Disabling IRQ ...\n");
+               pr_info("%s Disabling IRQ ...\n", __func__);
                disable_irq(wilc->dev_irq_num);
        } else {
-               PRINT_INFO(wilc->vif[0]->ndev, INT_DBG, "Disabling IRQ ...\n");
+               pr_info("%s Disabling IRQ ...\n", __func__);
                disable_irq_nosync(wilc->dev_irq_num);
        }
 }
@@ -247,13 +143,9 @@ static irqreturn_t host_wakeup_isr(int irq, void *user_data)
 static irqreturn_t isr_uh_routine(int irq, void *user_data)
 {
        struct wilc *wilc = (struct wilc *)user_data;
-       struct net_device *dev = wilc->vif[0]->ndev;
-
-
-       PRINT_INFO(dev, INT_DBG, "Interrupt received UH\n");
 
        if (wilc->close) {
-               PRINT_ER(dev, "Can't handle UH interrupt\n");
+               pr_err("%s: Can't handle UH interrupt\n", __func__);
                return IRQ_HANDLED;
        }
        return IRQ_WAKE_THREAD;
@@ -262,15 +154,12 @@ static irqreturn_t isr_uh_routine(int irq, void *user_data)
 static irqreturn_t isr_bh_routine(int irq, void *userdata)
 {
        struct wilc *wilc = (struct wilc *)userdata;
-       struct net_device *dev = wilc->vif[0]->ndev;
-
 
        if (wilc->close) {
-               PRINT_ER(dev, "Can't handle BH interrupt\n");
+               pr_err("%s: Can't handle BH interrupt\n", __func__);
                return IRQ_HANDLED;
        }
 
-       PRINT_INFO(dev, INT_DBG, "Interrupt received BH\n");
        wilc_handle_isr(wilc);
 
        return IRQ_HANDLED;
@@ -329,7 +218,7 @@ static int init_irq(struct net_device *dev)
        if (wl->io_type == WILC_HIF_SPI ||
                wl->io_type == WILC_HIF_SDIO_GPIO_IRQ) {
                if (request_threaded_irq(wl->dev_irq_num, isr_uh_routine,
-                                        isr_bh_routine, IRQF_TRIGGER_LOW |
+                                        isr_bh_routine, IRQF_TRIGGER_FALLING |
                                                        IRQF_ONESHOT |
                                                        IRQF_NO_SUSPEND,
                                         "WILC_IRQ", wl) < 0) {
@@ -412,7 +301,7 @@ void wilc_frmw_to_host(struct wilc_vif *vif, u8 *buff, u32 size,
        u8 null_bssid[ETH_ALEN] = {0};
 
        buff += pkt_offset;
-       priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy);
+       priv = &vif->priv;
 
        if (size == 0) {
                PRINT_ER(vif->ndev,
@@ -533,42 +422,21 @@ void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode)
 {
        struct wilc_vif *vif = netdev_priv(wilc_netdev);
        struct wilc *wilc = vif->wilc;
-       u8 i = 0;
+       int srcu_idx;
 
-       PRINT_INFO(vif->ndev, GENERIC_DBG, "set bssid on[%p]\n", wilc_netdev);
-       for (i = 0; i < wilc->vif_num; i++) {
-               if (wilc_netdev == wilc->vif[i]->ndev) {
+       srcu_idx = srcu_read_lock(&wilc->srcu);
+       list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
+               if (wilc_netdev == vif->ndev) {
                        if (bssid)
-                               ether_addr_copy(wilc->vif[i]->bssid, bssid);
+                               ether_addr_copy(vif->bssid, bssid);
                        else
-                               eth_zero_addr(wilc->vif[i]->bssid);
+                               eth_zero_addr(vif->bssid);
                        PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "set bssid [%pM]\n", wilc->vif[i]->bssid);
-                       wilc->vif[i]->iftype = mode;
+                                  "set bssid [%pM]\n", vif->bssid);
+                       vif->iftype = mode;
                }
        }
-}
-
-int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc)
-{
-       u8 i = 0;
-       u8 ret_val = 0;
-
-       for (i = 0; i < wilc->vif_num; i++)
-               if (!is_zero_ether_addr(wilc->vif[i]->bssid))
-                       ret_val++;
-
-       return ret_val;
-}
-
-struct net_device *wilc_get_if_netdev(struct wilc *wilc, uint8_t ifc)
-{
-       return wilc->vif[ifc]->ndev;
-}
-
-struct host_if_drv *get_drv_hndl_by_ifc(struct wilc *wilc, uint8_t ifc)
-{
-       return wilc->vif[ifc]->hif_drv;
+       srcu_read_unlock(&wilc->srcu, srcu_idx);
 }
 
 #define TX_BACKOFF_WEIGHT_INCR_STEP (1)
@@ -577,19 +445,19 @@ struct host_if_drv *get_drv_hndl_by_ifc(struct wilc *wilc, uint8_t ifc)
 #define TX_BACKOFF_WEIGHT_MIN (0)
 #define TX_BCKOFF_WGHT_MS (1)
 
-
 static int wilc_txq_task(void *vp)
 {
        int ret;
        u32 txq_count;
-       struct net_device *ndev = vp;
        int backoff_weight = TX_BACKOFF_WEIGHT_MIN;
        signed long timeout;
-       struct wilc_vif *vif = netdev_priv(ndev);
-       struct wilc *wl = vif->wilc;
+       struct wilc *wl = vp;
 
        complete(&wl->txq_thread_started);
        while (1) {
+               struct wilc_vif *vif = wilc_get_wl_to_vif(wl);
+               struct net_device *ndev = vif->ndev;
+
                PRINT_INFO(ndev, TX_DBG, "txq_task Taking a nap\n");
                wait_for_completion(&wl->txq_event);
                PRINT_INFO(ndev, TX_DBG, "txq_task Who waked me up\n");
@@ -603,16 +471,21 @@ static int wilc_txq_task(void *vp)
                }
                PRINT_INFO(ndev, TX_DBG, "handle the tx packet\n");
                do {
-                       ret = wilc_wlan_handle_txq(ndev, &txq_count);
+                       ret = wilc_wlan_handle_txq(wl, &txq_count);
                        if (txq_count < FLOW_CTRL_LOW_THRESHLD) {
+                               struct wilc_vif *ifc;
+                               int srcu_idx;
+
+                               srcu_idx = srcu_read_lock(&wl->srcu);
                                PRINT_INFO(ndev, TX_DBG, "Waking up queue\n");
-                               if (wl->vif[0]->mac_opened &&
-                                   netif_queue_stopped(wl->vif[0]->ndev))
-                                       netif_wake_queue(wl->vif[0]->ndev);
+                               list_for_each_entry_rcu(ifc, &wl->vif_list,
+                                                       list) {
+                                       if (ifc->mac_opened &&
+                                           netif_queue_stopped(ifc->ndev))
+                                               netif_wake_queue(ifc->ndev);
+                               }
+                               srcu_read_unlock(&wl->srcu, srcu_idx);
 
-                               if (wl->vif[1]->mac_opened &&
-                                   netif_queue_stopped(wl->vif[1]->ndev))
-                                       netif_wake_queue(wl->vif[1]->ndev);
                        }
 
                        if (ret == -ENOBUFS) {
@@ -650,7 +523,6 @@ static int wilc_wlan_get_firmware(struct net_device *dev)
        const struct firmware *wilc_firmware;
        char *firmware;
 
-
        if (wilc->chip == WILC_3000) {
                PRINT_INFO(dev, INIT_DBG, "Detect chip WILC3000\n");
                firmware = FW_WILC3000_WIFI;
@@ -733,14 +605,13 @@ fail:
 
 static int wilc_init_fw_config(struct net_device *dev, struct wilc_vif *vif)
 {
-       struct wilc_priv *priv;
+       struct wilc_priv *priv = &vif->priv;
        struct host_if_drv *hif_drv;
        u8 b;
        u16 hw;
        u32 w;
 
        PRINT_INFO(vif->ndev, INIT_DBG, "Start configuring Firmware\n");
-       priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
        hif_drv = (struct host_if_drv *)priv->hif_drv;
        PRINT_D(vif->ndev, INIT_DBG, "Host = %p\n", hif_drv);
 
@@ -908,17 +779,6 @@ fail:
        return -1;
 }
 
-static void wlan_deinit_locks(struct wilc *wilc)
-{
-       pr_info("De-Initializing Locks\n");
-
-       mutex_destroy(&wilc->hif_cs);
-       mutex_destroy(&wilc->rxq_cs);
-       mutex_destroy(&wilc->cfg_cmd_lock);
-       mutex_destroy(&wilc->txq_add_to_head_cs);
-       mutex_destroy(&wilc->cs);
-}
-
 static void wlan_deinitialize_threads(struct net_device *dev)
 {
        struct wilc_vif *vif = netdev_priv(dev);
@@ -982,7 +842,7 @@ static void wilc_wlan_deinitialize(struct net_device *dev)
                deinit_irq(dev);
 
                ret = wilc_wlan_stop(wl, vif);
-               if (ret == 0)
+               if (ret != 0)
                        PRINT_ER(dev, "failed in wlan_stop\n");
 
                PRINT_INFO(vif->ndev, INIT_DBG, "Deinitializing WILC Wlan\n");
@@ -996,26 +856,6 @@ static void wilc_wlan_deinitialize(struct net_device *dev)
        }
 }
 
-static void wlan_init_locks(struct wilc *wl)
-{
-       pr_info("Initializing Locks ...\n");
-
-       mutex_init(&wl->rxq_cs);
-       mutex_init(&wl->cfg_cmd_lock);
-
-       spin_lock_init(&wl->txq_spinlock);
-       mutex_init(&wl->txq_add_to_head_cs);
-       mutex_init(&wl->hif_cs);
-       mutex_init(&wl->cs);
-
-       init_completion(&wl->txq_event);
-
-       init_completion(&wl->cfg_event);
-       init_completion(&wl->sync_event);
-       init_completion(&wl->txq_thread_started);
-       init_completion(&wl->debug_thread_started);
-}
-
 static int wlan_initialize_threads(struct net_device *dev)
 {
        struct wilc_vif *vif = netdev_priv(dev);
@@ -1023,7 +863,7 @@ static int wlan_initialize_threads(struct net_device *dev)
 
        PRINT_INFO(vif->ndev, INIT_DBG, "Initializing Threads ...\n");
        PRINT_INFO(vif->ndev, INIT_DBG, "Creating kthread for transmission\n");
-       wilc->txq_thread = kthread_run(wilc_txq_task, (void *)dev,
+       wilc->txq_thread = kthread_run(wilc_txq_task, (void *)wilc,
                                       "K_TXQ_TASK");
        if (IS_ERR(wilc->txq_thread)) {
                PRINT_ER(dev, "couldn't create TXQ thread\n");
@@ -1035,7 +875,7 @@ static int wlan_initialize_threads(struct net_device *dev)
        if (!debug_running) {
                PRINT_INFO(vif->ndev, INIT_DBG,
                           "Creating kthread for Debugging\n");
-               wilc->debug_thread = kthread_run(debug_thread, (void *)dev,
+               wilc->debug_thread = kthread_run(debug_thread, (void *)wilc,
                                                 "WILC_DEBUG");
                if (IS_ERR(wilc->debug_thread)) {
                        PRINT_ER(dev, "couldn't create debug thread\n");
@@ -1063,15 +903,10 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
                ret = wilc_wlan_init(dev);
                if (ret < 0) {
                        PRINT_ER(dev, "Initializing WILC_Wlan FAILED\n");
-                       ret = -EIO;
-                       goto fail;
+                       return -EIO;
                }
                PRINT_INFO(vif->ndev, GENERIC_DBG,
                           "WILC Initialization done\n");
-               if (init_irq(dev)) {
-                       ret = -EIO;
-                       goto fail;
-               }
 
                ret = wlan_initialize_threads(dev);
                if (ret < 0) {
@@ -1080,6 +915,11 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
                        goto fail_wilc_wlan;
                }
 
+               if (init_irq(dev)) {
+                       ret = -EIO;
+                       goto fail_threads;
+               }
+
                if (wl->io_type == WILC_HIF_SDIO &&
                    wl->hif_func->enable_interrupt(wl)) {
                        PRINT_ER(dev, "couldn't initialize IRQ\n");
@@ -1138,10 +978,10 @@ fail_irq_enable:
 fail_irq_init:
                deinit_irq(dev);
 
+fail_threads:
                wlan_deinitialize_threads(dev);
 fail_wilc_wlan:
                wilc_wlan_cleanup(dev);
-fail:
                PRINT_ER(dev, "WLAN initialization FAILED\n");
        } else {
                PRINT_WRN(vif->ndev, INIT_DBG, "wilc already initialized\n");
@@ -1161,7 +1001,7 @@ static int wilc_mac_open(struct net_device *ndev)
 {
        struct wilc_vif *vif = netdev_priv(ndev);
        struct wilc *wl = vif->wilc;
-       struct wilc_priv *priv = wdev_priv(vif->ndev->ieee80211_ptr);
+       struct wilc_priv *priv = &vif->priv;
        unsigned char mac_add[ETH_ALEN] = {0};
        int ret = 0;
 
@@ -1193,19 +1033,8 @@ static int wilc_mac_open(struct net_device *ndev)
        }
 
        wait_for_recovery = 0;
-       if (!(memcmp(ndev->name, IFC_0, 5))) {
-               vif->ifc_id = WILC_WLAN_IFC;
-       } else if (!(memcmp(ndev->name, IFC_1, 4))) {
-               vif->ifc_id = WILC_P2P_IFC;
-       } else {
-               PRINT_ER(vif->ndev, "Unknown interface name\n");
-               wilc_deinit_host_int(ndev);
-               wilc_wlan_deinitialize(ndev);
-               return -ENODEV;
-       }
-       wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
-                                vif->iftype, vif->ifc_id);
-       wilc_set_operation_mode(vif, vif->iftype);
+       wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),
+                                vif->iftype, vif->idx);
        wilc_get_mac_address(vif, mac_add);
        PRINT_INFO(vif->ndev, INIT_DBG, "Mac address: %pM\n", mac_add);
 
@@ -1246,25 +1075,29 @@ static int wilc_set_mac_addr(struct net_device *dev, void *p)
        struct sockaddr *addr = (struct sockaddr *)p;
        struct wilc *wilc = vif->wilc;
        unsigned char mac_addr[6] = {0};
-       int i;
+       struct wilc_vif *tmp_vif;
+       int srcu_idx;
 
        if (!is_valid_ether_addr(addr->sa_data)) {
                PRINT_INFO(vif->ndev, INIT_DBG, "Invalid MAC address\n");
                return -EINVAL;
        }
 
-       for (i = 0; i < wilc->vif_num; i++) {
-               wilc_get_mac_address(wilc->vif[i], mac_addr);
+       srcu_idx = srcu_read_lock(&wilc->srcu);
+       list_for_each_entry_rcu(tmp_vif, &wilc->vif_list, list) {
+               wilc_get_mac_address(tmp_vif, mac_addr);
                if (ether_addr_equal(addr->sa_data, mac_addr)) {
-                       if (vif != wilc->vif[i]) {
+                       if (vif != tmp_vif) {
                                PRINT_INFO(vif->ndev, INIT_DBG,
                                           "MAC address is alredy in use\n");
+                               srcu_read_unlock(&wilc->srcu, srcu_idx);
                                return -EINVAL;
-                       } else {
-                               return 0;
                        }
+                       srcu_read_unlock(&wilc->srcu, srcu_idx);
+                       return 0;
                }
        }
+       srcu_read_unlock(&wilc->srcu, srcu_idx);
 
        /* configure new MAC address */
        result = wilc_set_mac_address(vif, (u8 *)addr->sa_data);
@@ -1369,17 +1202,21 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev)
        PRINT_D(vif->ndev, TX_DBG, "Adding tx pkt to TX Queue\n");
        vif->netstats.tx_packets++;
        vif->netstats.tx_bytes += tx_data->size;
-       tx_data->bssid = wilc->vif[vif->idx]->bssid;
        tx_data->vif = vif;
        queue_count = txq_add_net_pkt(ndev, (void *)tx_data,
                                      tx_data->buff, tx_data->size,
                                      wilc_tx_complete);
 
        if (queue_count > FLOW_CTRL_UP_THRESHLD) {
-               if (wilc->vif[0]->mac_opened)
-                       netif_stop_queue(wilc->vif[0]->ndev);
-               if (wilc->vif[1]->mac_opened)
-                       netif_stop_queue(wilc->vif[1]->ndev);
+               struct wilc_vif *vif;
+               int srcu_idx;
+
+               srcu_idx = srcu_read_lock(&wilc->srcu);
+               list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
+                       if (vif->mac_opened)
+                               netif_stop_queue(vif->ndev);
+               }
+               srcu_read_unlock(&wilc->srcu, srcu_idx);
        }
 
        return NETDEV_TX_OK;
@@ -1402,6 +1239,8 @@ static int wilc_mac_close(struct net_device *ndev)
        if (vif->ndev) {
                netif_stop_queue(vif->ndev);
 
+       handle_connect_cancel(vif);
+
        if (!recovery_on)
                wilc_deinit_host_int(vif->ndev);
        }
@@ -1409,6 +1248,7 @@ static int wilc_mac_close(struct net_device *ndev)
        if (wl->open_ifcs == 0) {
                PRINT_INFO(ndev, GENERIC_DBG, "Deinitializing wilc\n");
                wl->close = 1;
+
                wilc_wlan_deinitialize(ndev);
        }
 
@@ -1419,22 +1259,24 @@ static int wilc_mac_close(struct net_device *ndev)
 
 void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
 {
-       int i = 0;
        struct wilc_vif *vif;
+       int srcu_idx;
+
+       srcu_idx = srcu_read_lock(&wilc->srcu);
+       list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
+               u16 tp = le16_to_cpup((__le16 *)buff);
+               struct wilc_priv *priv;
 
-       for (i = 0; i < wilc->vif_num; i++) {
-               u16 type;
+               priv = &vif->priv;
+               if (((tp == vif->frame_reg[0].type && vif->frame_reg[0].reg) ||
+                   (tp == vif->frame_reg[1].type && vif->frame_reg[1].reg)) &&
+                           vif->p2p_listen_state)
+                       wilc_wfi_p2p_rx(vif, buff, size);
 
-               vif = netdev_priv(wilc->vif[i]->ndev);
-               if (vif->monitor_flag) {
+               if (vif->monitor_flag)
                        wilc_wfi_monitor_rx(wilc->monitor_dev, buff, size);
-                       return;
-               }
-               type = le16_to_cpup((__le16 *)buff);
-               if ((type == vif->frame_reg[0].type && vif->frame_reg[0].reg) ||
-                   (type == vif->frame_reg[1].type && vif->frame_reg[1].reg))
-                       wilc_wfi_p2p_rx(vif->ndev, buff, size);
        }
+       srcu_read_unlock(&wilc->srcu, srcu_idx);
 }
 
 static const struct net_device_ops wilc_netdev_ops = {
@@ -1447,84 +1289,10 @@ static const struct net_device_ops wilc_netdev_ops = {
        .ndo_set_rx_mode  = wilc_set_multicast_list,
 };
 
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-static int dev_state_ev_handler(struct notifier_block *this,
-                               unsigned long event, void *ptr)
-{
-       struct in_ifaddr *dev_iface = ptr;
-       struct wilc_priv *priv;
-       struct host_if_drv *hif_drv;
-       struct net_device *dev;
-       struct wilc_vif *vif;
-
-       if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev) {
-               pr_err("dev_iface = NULL\n");
-               return NOTIFY_DONE;
-       }
-
-       dev  = (struct net_device *)dev_iface->ifa_dev->dev;
-       if (dev->netdev_ops != &wilc_netdev_ops) {
-               pr_info("interface is not ours\n");
-               return NOTIFY_DONE;
-       }
-
-       if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) {
-               pr_err("No Wireless registerd\n");
-               return NOTIFY_DONE;
-       }
-
-       priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
-       if (!priv) {
-               pr_err("No Wireless Priv\n");
-               return NOTIFY_DONE;
-       }
-       vif = netdev_priv(dev);
-       hif_drv = (struct host_if_drv *)priv->hif_drv;
-       if (!vif || !hif_drv) {
-               PRINT_WRN(vif->ndev, GENERIC_DBG, "No Wireless Priv\n");
-               return NOTIFY_DONE;
-       }
-
-       switch (event) {
-       case NETDEV_UP:
-               PRINT_INFO(vif->ndev, GENERIC_DBG, "event NETDEV_UP%p\n", dev);
-               PRINT_D(vif->ndev, GENERIC_DBG,
-                       "\n =========== IP Address Obtained ============\n\n");
-               if (vif->iftype == WILC_STATION_MODE ||
-                   vif->iftype == WILC_CLIENT_MODE) {
-                       hif_drv->ifc_up = 1;
-
-                       handle_pwrsave_for_IP(vif, IP_STATE_OBTAINED);
-               }
-               break;
-
-       case NETDEV_DOWN:
-               PRINT_INFO(vif->ndev, GENERIC_DBG, "event=NETDEV_DOWN %p\n",
-                          dev);
-               if (vif->iftype == WILC_STATION_MODE ||
-                   vif->iftype == WILC_CLIENT_MODE) {
-                       hif_drv->ifc_up = 0;
-                       handle_pwrsave_for_IP(vif, IP_STATE_DEFAULT);
-               }
-               break;
-
-       default:
-               PRINT_INFO(vif->ndev, GENERIC_DBG,
-                          "[%s] unknown dev event %lu\n",
-                          dev_iface->ifa_label, event);
-               break;
-       }
-
-       return NOTIFY_DONE;
-}
-static struct notifier_block g_dev_notifier = {
-       .notifier_call = dev_state_ev_handler
-};
-#endif
-
 void wilc_netdev_cleanup(struct wilc *wilc)
 {
-       int i;
+       struct wilc_vif *vif;
+       int srcu_idx;
 
        if (!wilc)
                return;
@@ -1534,28 +1302,39 @@ void wilc_netdev_cleanup(struct wilc *wilc)
                wilc->firmware = NULL;
        }
 
-       for (i = WILC_NUM_CONCURRENT_IFC - 1 ; i >= 0; i--)
-               if (wilc->vif[i] && wilc->vif[i]->ndev) {
-                       PRINT_INFO(wilc->vif[i]->ndev, INIT_DBG,
+       srcu_idx = srcu_read_lock(&wilc->srcu);
+       list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
+               /* clear the mode */
+               wilc_set_operation_mode(vif, 0, 0, 0);
+               if (vif->ndev) {
+                       PRINT_INFO(vif->ndev, INIT_DBG,
                                   "Unregistering netdev %p\n",
-                                  wilc->vif[i]->ndev);
-                       unregister_netdev(wilc->vif[i]->ndev);
-                       PRINT_INFO(wilc->vif[i]->ndev, INIT_DBG,
-                                  "Freeing Wiphy...\n");
-                       wilc_free_wiphy(wilc->vif[i]->ndev);
-                       PRINT_INFO(wilc->vif[i]->ndev, INIT_DBG,
-                                  "Freeing netdev...\n");
-                       free_netdev(wilc->vif[i]->ndev);
+                                  vif->ndev);
+                       unregister_netdev(vif->ndev);
                }
+       }
+       srcu_read_unlock(&wilc->srcu, srcu_idx);
 
-       wilc_wfi_deinit_mon_interface(wilc);
-       #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-               unregister_inetaddr_notifier(&g_dev_notifier);
-       #endif
+       wilc_wfi_deinit_mon_interface(wilc, false);
 
        flush_workqueue(wilc->hif_workqueue);
        destroy_workqueue(wilc->hif_workqueue);
        wilc->hif_workqueue = NULL;
+       /* update the list */
+       do {
+               mutex_lock(&wilc->vif_mutex);
+               if (wilc->vif_num <= 0) {
+                       mutex_unlock(&wilc->vif_mutex);
+                       break;
+               }
+               vif = wilc_get_wl_to_vif(wilc);
+               if (!IS_ERR(vif))
+                       list_del_rcu(&vif->list);
+               wilc->vif_num--;
+               mutex_unlock(&wilc->vif_mutex);
+               synchronize_srcu(&wilc->srcu);
+       } while (1);
+
        cfg_deinit(wilc);
 #ifdef WILC_DEBUGFS
        wilc_debugfs_remove();
@@ -1563,141 +1342,94 @@ void wilc_netdev_cleanup(struct wilc *wilc)
        wilc_sysfs_exit();
        wlan_deinit_locks(wilc);
        kfree(wilc->bus_data);
-       kfree(wilc);
+       wiphy_unregister(wilc->wiphy);
+       pr_info("Freeing wiphy\n");
+       wiphy_free(wilc->wiphy);
        pr_info("Module_exit Done.\n");
 }
 
-int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type,
-                    const struct wilc_hif_func *ops)
+
+static u8 wilc_get_available_idx(struct wilc *wl)
 {
-       int i, ret;
+       int idx = 0;
        struct wilc_vif *vif;
-       struct net_device *ndev;
-       struct wilc *wl;
-       struct wireless_dev *wdev;
-
-       wl = kzalloc(sizeof(*wl), GFP_KERNEL);
-       if (!wl)
-               return -ENOMEM;
-
-       *wilc = wl;
-
-       wlan_init_locks(wl);
+       int srcu_idx;
 
-       ret = cfg_init(wl);
-       if (ret)
-               goto free_locks;
-
-#ifdef WILC_DEBUGFS
-       if (wilc_debugfs_init()) {
-               ret = -ENOMEM;
-               goto free_cfg;
-       }
-#endif
-       wl->io_type = io_type;
-       wl->hif_func = ops;
-
-       for (i = 0; i < NQUEUES; i++)
-               INIT_LIST_HEAD(&wl->txq[i].txq_head.list);
-
-       INIT_LIST_HEAD(&wl->rxq_head.list);
-
-       wl->hif_workqueue = create_singlethread_workqueue("WILC_wq");
-       if (!wl->hif_workqueue) {
-               ret = -ENOMEM;
-               goto free_debug_fs;
+       srcu_idx = srcu_read_lock(&wl->srcu);
+       list_for_each_entry_rcu(vif, &wl->vif_list, list) {
+               if (vif->idx == 0)
+                       idx = 1;
+               else
+                       idx = 0;
        }
+       srcu_read_unlock(&wl->srcu, srcu_idx);
+       return idx;
+}
 
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-       register_inetaddr_notifier(&g_dev_notifier);
-#endif
-
-       for (i = 0; i < WILC_NUM_CONCURRENT_IFC; i++) {
-               ndev = alloc_etherdev(sizeof(struct wilc_vif));
-               if (!ndev) {
-                       ret = -ENOMEM;
-                       goto free_ndev;
-               }
-
-               vif = netdev_priv(ndev);
+struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
+                                     int iftype, enum nl80211_iftype type,
+                                     bool rtnl_locked)
+{
+       struct net_device *ndev;
+       struct wilc_vif *vif;
+       int ret;
 
-               if (i == 0)
-                       strcpy(ndev->name, "wlan%d");
-               else
-                       strcpy(ndev->name, "p2p%d");
+       ndev = alloc_etherdev(sizeof(struct wilc_vif));
+       if (!ndev)
+               return ERR_PTR(-ENOMEM);
 
-               vif->idx = wl->vif_num;
-               vif->wilc = *wilc;
-               vif->ndev = ndev;
-               wl->vif[i] = vif;
-               wl->vif_num = i + 1;
+       vif = netdev_priv(ndev);
 
-               ndev->netdev_ops = &wilc_netdev_ops;
+       ndev->ieee80211_ptr = &vif->priv.wdev;
 
-               wdev = wilc_create_wiphy(ndev, dev);
-               if (!wdev) {
-                       PRINT_ER(ndev, "Can't register WILC Wiphy\n");
-                       ret = -ENOMEM;
-                       goto free_ndev;
-               }
+       vif->wilc = wl;
+       vif->ndev = ndev;
+       ndev->ml_priv = vif;
+       strcpy(ndev->name, name);
+       ndev->netdev_ops = &wilc_netdev_ops;
 
-               SET_NETDEV_DEV(ndev, dev);
+       SET_NETDEV_DEV(ndev, wiphy_dev(wl->wiphy));
 
-               vif->ndev->ieee80211_ptr = wdev;
-               vif->ndev->ml_priv = vif;
-               wdev->netdev = vif->ndev;
-               vif->netstats.rx_packets = 0;
-               vif->netstats.tx_packets = 0;
-               vif->netstats.rx_bytes = 0;
-               vif->netstats.tx_bytes = 0;
+       vif->ndev->ml_priv = vif;
+       vif->priv.wdev.wiphy = wl->wiphy;
+       vif->priv.wdev.netdev = ndev;
+       vif->priv.wdev.iftype = type;
+       vif->priv.dev = ndev;
 
+       vif->priv.dev = ndev;
+       if (rtnl_locked)
+               ret = register_netdevice(ndev);
+       else
                ret = register_netdev(ndev);
-               if (ret) {
-                       PRINT_ER(ndev, "Device couldn't be registered - %s\n",
-                              ndev->name);
-                       goto free_ndev;
-               }
 
-               vif->iftype = WILC_STATION_MODE;
-               vif->mac_opened = 0;
-       }
-       wilc_sysfs_init(wl->vif[0], wl->vif[1]);
-
-       return 0;
-free_ndev:
-       for (; i >= 0; i--) {
-               if (wl->vif[i]) {
-                       if (wl->vif[i]->iftype == WILC_STATION_MODE)
-                               unregister_netdev(wl->vif[i]->ndev);
-
-                       if (wl->vif[i]->ndev) {
-                               wilc_free_wiphy(wl->vif[i]->ndev);
-                               free_netdev(wl->vif[i]->ndev);
-                       }
-               }
+       if (ret) {
+               pr_err("Device couldn't be registered - %s\n", ndev->name);
+               free_netdev(ndev);
+               return ERR_PTR(-EFAULT);
        }
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-       unregister_inetaddr_notifier(&g_dev_notifier);
+#if KERNEL_VERSION(4, 11, 9) <= LINUX_VERSION_CODE
+       ndev->needs_free_netdev = true;
+#else
+       ndev->destructor = free_netdev;
 #endif
-       destroy_workqueue(wl->hif_workqueue);
+       vif->iftype = iftype;
+       vif->idx = wilc_get_available_idx(wl);
+       vif->mac_opened = 0;
+       mutex_lock(&wl->vif_mutex);
+       wl->vif_num += 1;
+       list_add_tail_rcu(&vif->list, &wl->vif_list);
+       mutex_unlock(&wl->vif_mutex);
+       synchronize_srcu(&wl->srcu);
 
-free_debug_fs:
-#ifdef WILC_DEBUGFS
-       wilc_debugfs_remove();
-free_cfg:
-#endif
-       cfg_deinit(wl);
-free_locks:
-       wlan_deinit_locks(wl);
-       kfree(wl);
-       return ret;
+       return vif;
 }
 
 #if KERNEL_VERSION(3, 13, 0) < LINUX_VERSION_CODE
-static void wilc_wlan_power(struct wilc *wilc, int power)
+static int wilc_wlan_power(struct wilc *wilc, int power)
 {
        struct gpio_desc *gpio_reset;
        struct gpio_desc *gpio_chip_en;
+       int ret = 0;
 
        pr_info("wifi_pm : %d\n", power);
 
@@ -1708,7 +1440,7 @@ static void wilc_wlan_power(struct wilc *wilc, int power)
                if (!gpio_reset) {
                        dev_warn(wilc->dev,
                                 "failed to get default Reset GPIO\r\n");
-                       return;
+                       return -EIO;
                }
        } else {
                dev_info(wilc->dev, "succesfully got gpio_reset\r\n");
@@ -1721,25 +1453,53 @@ static void wilc_wlan_power(struct wilc *wilc, int power)
                        dev_warn(wilc->dev,
                                 "failed to get default chip_en GPIO\r\n");
                        gpiod_put(gpio_reset);
-                       return;
+                       return -EIO;
                }
        } else {
                dev_info(wilc->dev, "succesfully got gpio_chip_en\r\n");
        }
 
        if (power) {
-               gpiod_direction_output(gpio_chip_en, 1);
+               ret = gpiod_direction_output(gpio_chip_en, 1);
+               if (ret < 0) {
+                       dev_warn(wilc->dev,
+                                "failed to set chip_en GPIO direction\r\n");
+                       goto out;
+                       ret = -EIO;
+               }
                mdelay(5);
-               gpiod_direction_output(gpio_reset, 1);
+               ret = gpiod_direction_output(gpio_reset, 1);
+               if (ret) {
+                       dev_warn(wilc->dev,
+                                "failed to set reset GPIO direction\r\n");
+                       goto out;
+                       ret = -EIO;
+               }
        } else {
-               gpiod_direction_output(gpio_reset, 0);
-               gpiod_direction_output(gpio_chip_en, 0);
+               ret = gpiod_direction_output(gpio_reset, 0);
+               if (ret) {
+                       dev_warn(wilc->dev,
+                                "failed to set chip_en GPIO direction\r\n");
+                       goto out;
+                       ret = -EIO;
+               }
+               ret = gpiod_direction_output(gpio_chip_en, 0);
+               if (ret) {
+                       dev_warn(wilc->dev,
+                                "failed to set reset GPIO direction\r\n");
+                       goto out;
+                       ret = -EIO;
+               }
        }
+
+out:
        gpiod_put(gpio_chip_en);
        gpiod_put(gpio_reset);
+
+       return ret;
 }
 #else
-static void wilc_wlan_power(struct wilc *wilc, int power)
+static int wilc_wlan_power(struct wilc *wilc, int power)
 {
        int gpio_reset;
        int gpio_chip_en;
@@ -1780,20 +1540,36 @@ static void wilc_wlan_power(struct wilc *wilc, int power)
        } else {
                dev_err(wilc->dev,
                        "Error requesting GPIOs for CHIP_EN and RESET");
+               return -EIO;
        }
 
+       return 0;
 }
 #endif
 
-void wilc_wlan_power_on_sequence(struct wilc *wilc)
+int wilc_wlan_power_on_sequence(struct wilc *wilc)
 {
-       wilc_wlan_power(wilc, 0);
-       wilc_wlan_power(wilc, 1);
+       int ret;
+
+       ret = wilc_wlan_power(wilc, 0);
+       if (ret)
+               return ret;
+       ret = wilc_wlan_power(wilc, 1);
+       if (ret)
+               return ret;
+
+       return 0;
 }
 
-void wilc_wlan_power_off_sequence(struct wilc *wilc)
+int wilc_wlan_power_off_sequence(struct wilc *wilc)
 {
-       wilc_wlan_power(wilc, 0);
+       int ret;
+
+       ret = wilc_wlan_power(wilc, 0);
+       if (ret)
+               return ret;
+
+       return 0;
 }
 
 MODULE_LICENSE("GPL");
index d882ea3..f260fac 100644 (file)
 #include "wilc_wfi_netdevice.h"
 #include "wilc_wlan_if.h"
 
-#define IP_STATE_OBTAINING             1
-#define IP_STATE_OBTAINED              2
-#define IP_STATE_GO_ASSIGNING          3
-#define IP_STATE_DEFAULT               4
-
 extern int wait_for_recovery;
 
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-void handle_pwrsave_for_IP(struct wilc_vif *vif, uint8_t state);
-void store_power_save_current_state(struct wilc_vif *vif, bool val);
-#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
-void clear_during_ip(struct timer_list *t);
-#else
-void clear_during_ip(unsigned long arg);
-#endif
-#endif //DISABLE_PWRSAVE_AND_SCAN_DURING_IP
 struct net_device *wilc_get_if_netdev(struct wilc *wilc, uint8_t ifc);
-struct host_if_drv *get_drv_hndl_by_ifc(struct wilc *wilc, uint8_t ifc);
 
 #if KERNEL_VERSION(3, 14, 0) > LINUX_VERSION_CODE
 static inline void ether_addr_copy(u8 *dst, const u8 *src)
@@ -58,8 +43,15 @@ static inline bool ether_addr_equal_unaligned(const u8 *addr1, const u8 *addr2)
 }
 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */
 
+#if KERNEL_VERSION(3, 12, 0) > LINUX_VERSION_CODE
+#define PTR_ERR_OR_ZERO(ptr) PTR_RET(ptr)
+#endif
+
 int wilc_bt_power_up(struct wilc *wilc, int source);
 int wilc_bt_power_down(struct wilc *wilc, int source);
 void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size);
+struct wilc_vif *
+wilc_netdev_ifc_init(struct wilc *wl, const char *name, int iftype,
+                    enum nl80211_iftype type, bool rtnl_locked);
 
 #endif /* WILC_NETDEV_H */
index a3fc4fb..8e2bfe6 100644 (file)
@@ -4,6 +4,7 @@
  * All rights reserved.
  */
 
+#include <linux/clk.h>
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
@@ -12,6 +13,8 @@
 
 #include "wilc_wfi_netdevice.h"
 #include "wilc_wlan.h"
+#include "wilc_wfi_cfgoperations.h"
+#include "wilc_netdev.h"
 
 enum sdio_host_lock {
        WILC_SDIO_HOST_NO_TAKEN = 0,
@@ -39,6 +42,7 @@ struct wilc_sdio {
        u32 block_size;
        int nint;
        bool is_init;
+       struct wilc *wl;
 };
 
 struct sdio_cmd52 {
@@ -134,7 +138,7 @@ static int wilc_sdio_cmd53(struct wilc *wilc, struct sdio_cmd53 *cmd)
 }
 
 static int wilc_sdio_probe(struct sdio_func *func,
-                           const struct sdio_device_id *id)
+                          const struct sdio_device_id *id)
 {
        struct wilc *wilc;
        int ret, io_type;
@@ -150,7 +154,7 @@ static int wilc_sdio_probe(struct sdio_func *func,
        else
                io_type = WILC_HIF_SDIO;
        dev_dbg(&func->dev, "Initializing netdev\n");
-       ret = wilc_netdev_init(&wilc, &func->dev, io_type, &wilc_hif_sdio);
+       ret = wilc_cfg80211_init(&wilc, &func->dev, io_type, &wilc_hif_sdio);
        if (ret) {
                dev_err(&func->dev, "Couldn't initialize netdev\n");
                kfree(sdio_priv);
@@ -160,9 +164,21 @@ static int wilc_sdio_probe(struct sdio_func *func,
        wilc->bus_data = sdio_priv;
        wilc->dev = &func->dev;
        wilc->dt_dev = &func->card->dev;
+       sdio_priv->wl = wilc;
+
+       wilc->rtc_clk = devm_clk_get(&func->card->dev, "rtc_clk");
+       if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
+       else if (!IS_ERR(wilc->rtc_clk))
+               clk_prepare_enable(wilc->rtc_clk);
 
        if (!init_power) {
-               wilc_wlan_power_on_sequence(wilc);
+               ret = wilc_wlan_power_on_sequence(wilc);
+               if (ret) {
+                       wilc_netdev_cleanup(wilc);
+                       kfree(sdio_priv);
+                       return ret;
+               }
                init_power = 1;
        }
 
@@ -176,6 +192,9 @@ static void wilc_sdio_remove(struct sdio_func *func)
 {
        struct wilc *wilc = sdio_get_drvdata(func);
 
+       if (!IS_ERR(wilc->rtc_clk))
+               clk_disable_unprepare(wilc->rtc_clk);
+
        wilc_netdev_cleanup(wilc);
        wilc_bt_deinit();
 }
@@ -1155,4 +1174,5 @@ module_driver(wilc_sdio_driver,
              sdio_register_driver,
              sdio_unregister_driver);
 MODULE_LICENSE("GPL");
+MODULE_VERSION("15.3");
 
index c20fbf4..db9cf2d 100644 (file)
@@ -4,10 +4,13 @@
  * All rights reserved.
  */
 
+#include <linux/clk.h>
 #include <linux/spi/spi.h>
 #include <linux/module.h>
 
 #include "wilc_wfi_netdevice.h"
+#include "wilc_wfi_cfgoperations.h"
+#include "wilc_netdev.h"
 
 struct wilc_spi {
        int crc_off;
@@ -123,7 +126,7 @@ static int wilc_bus_probe(struct spi_device *spi)
        if (!spi_priv)
                return -ENOMEM;
 
-       ret = wilc_netdev_init(&wilc, dev, WILC_HIF_SPI, &wilc_hif_spi);
+       ret = wilc_cfg80211_init(&wilc, dev, WILC_HIF_SPI, &wilc_hif_spi);
        if (ret) {
                kfree(spi_priv);
                return ret;
@@ -134,9 +137,19 @@ static int wilc_bus_probe(struct spi_device *spi)
        wilc->bus_data = spi_priv;
        wilc->dt_dev = &spi->dev;
 
+       wilc->rtc_clk = devm_clk_get(&spi->dev, "rtc_clk");
+       if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
+       else if (!IS_ERR(wilc->rtc_clk))
+               clk_prepare_enable(wilc->rtc_clk);
 
        if (!init_power) {
-               wilc_wlan_power_on_sequence(wilc);
+               ret = wilc_wlan_power_on_sequence(wilc);
+               if (ret) {
+                       wilc_netdev_cleanup(wilc);
+                       kfree(spi_priv);
+                       return ret;
+               }
                init_power = 1;
        }
 
@@ -150,6 +163,9 @@ static int wilc_bus_remove(struct spi_device *spi)
 {
        struct wilc *wilc = spi_get_drvdata(spi);
 
+       if (!IS_ERR(wilc->rtc_clk))
+               clk_disable_unprepare(wilc->rtc_clk);
+
        wilc_netdev_cleanup(wilc);
        wilc_bt_deinit();
        return 0;
@@ -222,6 +238,7 @@ static struct spi_driver wilc_spi_driver = {
 };
 module_spi_driver(wilc_spi_driver);
 MODULE_LICENSE("GPL");
+MODULE_VERSION("15.3");
 
 static int spi_data_rsp(struct wilc *wilc, u8 cmd)
 {
@@ -524,7 +541,11 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz,
 
        rsp = rb[rix++];
 
-       if (rsp != cmd) {
+       /*
+        * Clockless registers operations might return unexptected responses,
+        * even if successful.
+        */
+       if (rsp != cmd && !clockless) {
                dev_err(&spi->dev,
                        "Failed cmd response, cmd (%02x), resp (%02x)\n",
                        cmd, rsp);
@@ -535,7 +556,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz,
         * State response
         */
        rsp = rb[rix++];
-       if (rsp != 0x00) {
+       if (rsp != 0x00 && !clockless) {
                dev_err(&spi->dev, "Failed cmd state response state (%02x)\n",
                        rsp);
                return N_FAIL;
@@ -562,7 +583,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz,
                                break;
                } while (retry--);
 
-               if (retry <= 0) {
+               if (retry <= 0 && !clockless) {
                        dev_err(&spi->dev,
                                "Error, data read response (%02x)\n", rsp);
                        return N_RESET;
index 4693ad9..4553637 100644 (file)
@@ -57,7 +57,7 @@ static const struct ieee80211_txrx_stypes
                        BIT(IEEE80211_STYPE_DISASSOC >> 4) |
                        BIT(IEEE80211_STYPE_AUTH >> 4) |
                        BIT(IEEE80211_STYPE_DEAUTH >> 4)
-       }
+       },
 };
 
 static const struct wiphy_wowlan_support wowlan_support = {
@@ -77,8 +77,10 @@ static void cfg_scan_result(enum scan_event scan_event,
 {
        struct wilc_priv *priv = user_void;
 
-       if (!priv->cfg_scanning)
+       if (!priv || !priv->cfg_scanning) {
+               pr_err("%s is NULL\n", __func__);
                return;
+       }
 
        if (scan_event == SCAN_EVENT_NETWORK_FOUND) {
                s32 freq;
@@ -153,6 +155,9 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt,
        struct wilc_vif *vif = netdev_priv(dev);
        struct host_if_drv *wfi_drv = priv->hif_drv;
        struct wilc_conn_info *conn_info = &wfi_drv->conn_info;
+#if KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE
+       struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+#endif
 
        vif->connecting = false;
 
@@ -174,7 +179,7 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt,
                }
 
                if (connect_status == WLAN_STATUS_SUCCESS) {
-                       PRINT_ER(dev,
+                       PRINT_INFO(vif->ndev, CFG80211_DBG,
                                "Connection Successful: BSSID: %x%x%x%x%x%x\n",
                                conn_info->bssid[0], conn_info->bssid[1],
                                conn_info->bssid[2], conn_info->bssid[3],
@@ -189,18 +194,36 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt,
                PRINT_INFO(vif->ndev, CFG80211_DBG,
                           "Association response info elements length = %d\n",
                           conn_info->resp_ies_len);
+#if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE
+               cfg80211_ref_bss(wiphy, vif->bss);
+               cfg80211_connect_bss(dev, conn_info->bssid, vif->bss,
+                                    conn_info->req_ies,
+                                    conn_info->req_ies_len,
+                                    conn_info->resp_ies,
+                                    conn_info->resp_ies_len,
+                                    connect_status, GFP_KERNEL,
+                                    NL80211_TIMEOUT_UNSPECIFIED);
+#elif KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE
+               cfg80211_ref_bss(wiphy, vif->bss);
+               cfg80211_connect_bss(dev, conn_info->bssid, vif->bss,
+                                    conn_info->req_ies,
+                                    conn_info->req_ies_len,
+                                    conn_info->resp_ies,
+                                    conn_info->resp_ies_len,
+                                    connect_status, GFP_KERNEL);
+#else
                cfg80211_connect_result(dev, conn_info->bssid,
                                        conn_info->req_ies,
                                        conn_info->req_ies_len,
                                        conn_info->resp_ies,
                                        conn_info->resp_ies_len, connect_status,
                                        GFP_KERNEL);
+#endif
+               vif->bss = NULL;
        } else if (conn_disconn_evt == EVENT_DISCONN_NOTIF) {
                u16 reason = 0;
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-               vif->obtaining_ip = false;
-#endif
-               PRINT_ER(vif->ndev,
+
+               PRINT_INFO(vif->ndev, CFG80211_DBG,
                         "Received WILC_MAC_STATUS_DISCONNECTED dev [%p]\n",
                         priv->dev);
                priv->p2p.local_random = 0x01;
@@ -225,33 +248,52 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt,
        }
 }
 
+struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl)
+{
+       struct wilc_vif *vif;
+
+       vif = list_first_or_null_rcu(&wl->vif_list, typeof(*vif), list);
+       if (!vif)
+               return ERR_PTR(-EINVAL);
+
+       return vif;
+}
+
 static int set_channel(struct wiphy *wiphy,
                       struct cfg80211_chan_def *chandef)
 {
+       struct wilc *wl = wiphy_priv(wiphy);
+       struct wilc_vif *vif;
        u32 channelnum = 0;
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
        int result = 0;
+       int srcu_idx;
+
+       srcu_idx = srcu_read_lock(&wl->srcu);
+       vif = wilc_get_wl_to_vif(wl);
+       if (IS_ERR(vif)) {
+               srcu_read_unlock(&wl->srcu, srcu_idx);
+               return 0;
+       }
 
        channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq);
        PRINT_INFO(vif->ndev, CFG80211_DBG,
                   "Setting channel %d with frequency %d\n",
                   channelnum, chandef->chan->center_freq);
 
-       vif->wilc->op_ch = channelnum;
+       wl->op_ch = channelnum;
        result = wilc_set_mac_chnl_num(vif, channelnum);
-
        if (result != 0)
-               PRINT_ER(priv->dev, "Error in setting channel %d\n",
+               PRINT_ER(vif->ndev, "Error in setting channel %d\n",
                         channelnum);
 
+       srcu_read_unlock(&wl->srcu, srcu_idx);
        return result;
 }
 
 static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc_vif *vif = netdev_priv(request->wdev->netdev);
+       struct wilc_priv *priv = &vif->priv;
        u32 i;
        int ret = 0;
        u8 scan_ch_list[WILC_MAX_NUM_SCANNED_CH];
@@ -305,8 +347,8 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
 static int connect(struct wiphy *wiphy, struct net_device *dev,
                   struct cfg80211_connect_params *sme)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc_vif *vif = netdev_priv(dev);
+       struct wilc_priv *priv = &vif->priv;
        struct host_if_drv *wfi_drv = priv->hif_drv;
        int ret;
        u32 i;
@@ -451,7 +493,6 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
                ret = -EINVAL;
                goto out_error;
        }
-
        if (ether_addr_equal_unaligned(vif->bssid, bss->bssid)) {
                ret = -EALREADY;
                goto out_put_bss;
@@ -464,7 +505,6 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
                ret = -EINVAL;
                goto out_put_bss;
        }
-
        ch = ieee80211_frequency_to_channel(bss->channel->center_freq);
        PRINT_D(vif->ndev, CFG80211_DBG, "Required Channel = %d\n", ch);
        vif->wilc->op_ch = ch;
@@ -492,6 +532,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev,
                goto out_put_bss;
        }
        kfree(join_params);
+       vif->bss = bss;
        cfg80211_put_bss(wiphy, bss);
        return 0;
 
@@ -506,8 +547,8 @@ out_error:
 static int disconnect(struct wiphy *wiphy, struct net_device *dev,
                      u16 reason_code)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc_vif *vif = netdev_priv(dev);
+       struct wilc_priv *priv = &vif->priv;
        struct wilc *wilc = vif->wilc;
        struct host_if_drv *wfi_drv;
        int ret;
@@ -534,6 +575,8 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev,
                ret = -EINVAL;
        }
 
+       vif->bss = NULL;
+
        return ret;
 }
 
@@ -595,13 +638,13 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
 
 {
        int ret = 0, keylen = params->key_len;
-       struct wilc_priv *priv = wiphy_priv(wiphy);
        const u8 *rx_mic = NULL;
        const u8 *tx_mic = NULL;
        u8 mode = WILC_FW_SEC_NO;
        u8 op_mode;
        int i;
        struct wilc_vif *vif = netdev_priv(netdev);
+       struct wilc_priv *priv = &vif->priv;
 
        PRINT_INFO(vif->ndev, CFG80211_DBG,
                   "Adding key with cipher suite = %x\n", params->cipher);
@@ -613,7 +656,7 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
        switch (params->cipher) {
        case WLAN_CIPHER_SUITE_WEP40:
        case WLAN_CIPHER_SUITE_WEP104:
-               if (priv->wdev->iftype == NL80211_IFTYPE_AP) {
+               if (priv->wdev.iftype == NL80211_IFTYPE_AP) {
                        wilc_wfi_cfg_copy_wep_info(priv, key_index, params);
 
                        PRINT_INFO(vif->ndev, CFG80211_DBG,
@@ -658,8 +701,8 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
 
        case WLAN_CIPHER_SUITE_TKIP:
        case WLAN_CIPHER_SUITE_CCMP:
-               if (priv->wdev->iftype == NL80211_IFTYPE_AP ||
-                   priv->wdev->iftype == NL80211_IFTYPE_P2P_GO) {
+               if (priv->wdev.iftype == NL80211_IFTYPE_AP ||
+                   priv->wdev.iftype == NL80211_IFTYPE_P2P_GO) {
                        struct wilc_wfi_key *key;
 
                        ret = wilc_wfi_cfg_allocate_wpa_entry(priv, key_index);
@@ -737,11 +780,11 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
                   const u8 *mac_addr)
 {
        int ret = 0;
-       struct wilc_priv *priv = wiphy_priv(wiphy);
        struct wilc_vif *vif = netdev_priv(netdev);
-       struct wilc *wl = vif->wilc;
+       struct wilc_priv *priv = &vif->priv;
 
-       if (netdev == wl->vif[0]->ndev) {
+       //TODO: Why to compare with only interface vif[0]
+       //if (netdev == wl->vif[0]->ndev) {
                if (priv->wilc_gtk[key_index]) {
                        kfree(priv->wilc_gtk[key_index]->key);
                        priv->wilc_gtk[key_index]->key = NULL;
@@ -760,14 +803,13 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
                        kfree(priv->wilc_ptk[key_index]);
                        priv->wilc_ptk[key_index] = NULL;
                }
-       }
+       //}
 
        if (key_index <= 3 && priv->wep_key_len[key_index]) {
                memset(priv->wep_key[key_index], 0,
                       priv->wep_key_len[key_index]);
                priv->wep_key_len[key_index] = 0;
-               PRINT_INFO(vif->ndev, CFG80211_DBG,
-                          "Removing WEP key with index = %d\n",
+               pr_info("%s: Removing WEP key with index = %d\n", __func__,
                           key_index);
                ret = wilc_remove_wep_key(vif, key_index);
        }
@@ -779,9 +821,9 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
                   bool pairwise, const u8 *mac_addr, void *cookie,
                   void (*callback)(void *cookie, struct key_params *))
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct  key_params key_params;
        struct wilc_vif *vif = netdev_priv(netdev);
+       struct wilc_priv *priv = &vif->priv;
+       struct  key_params key_params;
 
        if (!pairwise) {
                PRINT_INFO(vif->ndev, CFG80211_DBG,
@@ -808,8 +850,7 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
 static int set_default_key(struct wiphy *wiphy, struct net_device *netdev,
                           u8 key_index, bool unicast, bool multicast)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc_vif *vif = netdev_priv(netdev);
 
        wilc_set_wep_default_keyid(vif, key_index);
 
@@ -824,8 +865,8 @@ static int get_station(struct wiphy *wiphy, struct net_device *dev,
                       u8 *mac, struct station_info *sinfo)
 #endif
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
        struct wilc_vif *vif = netdev_priv(dev);
+       struct wilc_priv *priv = &vif->priv;
        struct wilc *wilc = vif->wilc;
        u32 i = 0;
        u32 associatedsta = ~0;
@@ -911,8 +952,19 @@ static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
 {
        int ret;
        struct cfg_param_attr cfg_param_val;
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc *wl = wiphy_priv(wiphy);
+       struct wilc_vif *vif;
+       struct wilc_priv *priv;
+       int srcu_idx;
+
+       srcu_idx = srcu_read_lock(&wl->srcu);
+       vif = wilc_get_wl_to_vif(wl);
+       if (IS_ERR(vif)) {
+               srcu_read_unlock(&wl->srcu, srcu_idx);
+               return 0;
+       }
+
+       priv = &vif->priv;
 
        cfg_param_val.flag = 0;
        PRINT_INFO(vif->ndev, CFG80211_DBG, "Setting Wiphy params\n");
@@ -942,7 +994,8 @@ static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
                } else {
                        PRINT_ER(vif->ndev,
                                 "Fragmentation threshold out of range\n");
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto out;
                }
        }
 
@@ -955,7 +1008,8 @@ static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
                        cfg_param_val.rts_threshold = wiphy->rts_threshold;
                } else {
                        PRINT_ER(vif->ndev, "RTS threshold out of range\n");
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto out;
                }
        }
 
@@ -965,14 +1019,17 @@ static int set_wiphy_params(struct wiphy *wiphy, u32 changed)
        if (ret)
                PRINT_ER(priv->dev, "Error in setting WIPHY PARAMS\n");
 
+out:
+       srcu_read_unlock(&wl->srcu, srcu_idx);
+
        return ret;
 }
 
 static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
                     struct cfg80211_pmksa *pmksa)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc_vif *vif = netdev_priv(netdev);
+       struct wilc_priv *priv = &vif->priv;
        u32 i;
        int ret = 0;
        u8 flag = 0;
@@ -1015,7 +1072,8 @@ static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
 {
        u32 i;
        int ret = 0;
-       struct wilc_priv *priv = wiphy_priv(wiphy);
+       struct wilc_vif *vif = netdev_priv(netdev);
+       struct wilc_priv *priv = &vif->priv;
 
        PRINT_INFO(netdev, CFG80211_DBG, "Deleting PMKSA keys\n");
 
@@ -1049,7 +1107,8 @@ static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
 
 static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
+       struct wilc_vif *vif = netdev_priv(netdev);
+       struct wilc_priv *priv = &vif->priv;
 
        PRINT_INFO(netdev, CFG80211_DBG, "Flushing  PMKID key values\n");
        memset(&priv->pmkid_list, 0, sizeof(struct wilc_pmkid_attr));
@@ -1067,9 +1126,6 @@ static inline void wilc_wfi_cfg_parse_ch_attr(struct wilc_vif *vif, u8 *buf,
        if (ch_list_attr_idx) {
                u8 limit = ch_list_attr_idx + 3 + buf[ch_list_attr_idx + 1];
 
-               PRINT_INFO(vif->ndev, GENERIC_DBG,
-                          "Modify channel list attribute [%d]\n",
-                          sta_ch);
                for (i = ch_list_attr_idx + 3; i < limit; i++) {
                        if (buf[i] == 0x51) {
                                for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++)
@@ -1080,9 +1136,6 @@ static inline void wilc_wfi_cfg_parse_ch_attr(struct wilc_vif *vif, u8 *buf,
        }
 
        if (op_ch_attr_idx) {
-               PRINT_INFO(vif->ndev, GENERIC_DBG,
-                          "Modify operating channel attribute %d\n",
-                          sta_ch);
                buf[op_ch_attr_idx + 6] = 0x51;
                buf[op_ch_attr_idx + 7] = sta_ch;
        }
@@ -1179,7 +1232,7 @@ static void wilc_wfi_cfg_parse_rx_vendor_spec(struct wilc_priv *priv, u8 *buff,
                for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < size; i++) {
                        if (buff[i] == P2PELEM_ATTR_ID &&
                            !(memcmp(p2p_oui, &buff[i + 2], 4))) {
-                               bool p2p_mode = vif->attr_sysfs.p2p_mode;
+                               bool p2p_mode = vif->wilc->attr_sysfs.p2p_mode;
 
                                wilc_wfi_cfg_parse_rx_action(vif, &buff[i + 6],
                                                             size - (i + 6),
@@ -1191,17 +1244,17 @@ static void wilc_wfi_cfg_parse_rx_vendor_spec(struct wilc_priv *priv, u8 *buff,
        }
 }
 
-void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
+bool wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size)
 {
-       struct wilc_priv *priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
-       struct host_if_drv *wfi_drv = priv->hif_drv;
-       struct wilc_vif *vif = netdev_priv(dev);
        struct wilc *wl = vif->wilc;
+       struct wilc_priv *priv = &vif->priv;
+       struct host_if_drv *wfi_drv = priv->hif_drv;
        u32 header, pkt_offset;
        s32 freq;
        __le16 fc;
+       int ret;
 
-       memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
+       header = get_unaligned_le32(buff - HOST_HDR_OFFSET);
 
        pkt_offset = GET_PKT_OFFSET(header);
 
@@ -1213,9 +1266,9 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
                    pkt_offset & IS_MGMT_STATUS_SUCCES)
                        ack = true;
 
-               cfg80211_mgmt_tx_status(priv->wdev, priv->tx_cookie, buff, size,
-                                       ack, GFP_KERNEL);
-               return;
+               cfg80211_mgmt_tx_status(&vif->priv.wdev, priv->tx_cookie, buff,
+                                       size, ack, GFP_KERNEL);
+               return true;
        }
 
        PRINT_D(vif->ndev, GENERIC_DBG, "Rx Frame Type:%x\n", fc);
@@ -1226,8 +1279,8 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
        freq = ieee80211_channel_to_frequency(wl->op_ch, IEEE80211_BAND_2GHZ);
  #endif
        if (!ieee80211_is_action(fc)) {
-               cfg80211_rx_mgmt(priv->wdev, freq, 0, buff, size, 0);
-               return;
+               ret = cfg80211_rx_mgmt(&vif->priv.wdev, freq, 0, buff, size, 0);
+               return ret;
        }
 
        PRINT_D(vif->ndev, GENERIC_DBG,
@@ -1236,8 +1289,9 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
                   buff[P2P_PUB_ACTION_SUBTYPE]);
        if (priv->cfg_scanning &&
            time_after_eq(jiffies, (unsigned long)wfi_drv->p2p_timeout)) {
-               PRINT_WRN(dev, GENERIC_DBG, "Receiving action wrong ch\n");
-               return;
+               PRINT_WRN(vif->ndev, GENERIC_DBG,
+                         "Receiving action wrong ch\n");
+               return false;
        }
        if (buff[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
                u8 subtype = buff[P2P_PUB_ACTION_SUBTYPE];
@@ -1267,14 +1321,13 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size)
                        break;
 
                default:
-                       PRINT_WRN(dev, GENERIC_DBG,
-                                  "Not handled action frame type:%x\n",
+                       pr_err("Not handled action frame type:%x\n",
                                   buff[ACTION_SUBTYPE_ID]);
                        break;
                }
        }
-
-       cfg80211_rx_mgmt(priv->wdev, freq, 0, buff, size, 0);
+       ret = cfg80211_rx_mgmt(&vif->priv.wdev, freq, 0, buff, size, 0);
+       return ret;
 }
 
 static void wilc_wfi_mgmt_tx_complete(void *priv, int status)
@@ -1287,7 +1340,8 @@ static void wilc_wfi_mgmt_tx_complete(void *priv, int status)
 
 static void wilc_wfi_remain_on_channel_expired(void *data, u64 cookie)
 {
-       struct wilc_priv *priv = data;
+       struct wilc_vif *vif = data;
+       struct wilc_priv *priv = &vif->priv;
        struct wilc_wfi_p2p_listen_params *params = &priv->remain_on_ch_params;
 
        if (cookie != priv->remain_on_ch_params.listen_cookie) {
@@ -1297,9 +1351,9 @@ static void wilc_wfi_remain_on_channel_expired(void *data, u64 cookie)
                return;
        }
 
-       priv->p2p_listen_state = false;
+       vif->p2p_listen_state = false;
 
-       cfg80211_remain_on_channel_expired(priv->wdev, cookie,
+       cfg80211_remain_on_channel_expired(&vif->priv.wdev, cookie,
                                           params->listen_ch, GFP_KERNEL);
 }
 
@@ -1309,16 +1363,12 @@ static int remain_on_channel(struct wiphy *wiphy,
                             unsigned int duration, u64 *cookie)
 {
        int ret = 0;
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc_vif *vif = netdev_priv(wdev->netdev);
+       struct wilc_priv *priv = &vif->priv;
        u64 id;
 
-       PRINT_INFO(vif->ndev, GENERIC_DBG, "Remaining on channel [%d]\n",
-                  chan->hw_value);
-
        if (wdev->iftype == NL80211_IFTYPE_AP) {
-               PRINT_INFO(vif->ndev, GENERIC_DBG,
-                          "Required while in AP mode\n");
+               pr_err("Required while in AP mode\n");
                return ret;
        }
 
@@ -1328,7 +1378,7 @@ static int remain_on_channel(struct wiphy *wiphy,
 
        ret = wilc_remain_on_channel(vif, id, duration, chan->hw_value,
                                     wilc_wfi_remain_on_channel_expired,
-                                    (void *)priv);
+                                    (void *)vif);
        if (ret)
                return ret;
 
@@ -1337,20 +1387,18 @@ static int remain_on_channel(struct wiphy *wiphy,
        priv->remain_on_ch_params.listen_cookie = id;
        *cookie = id;
        priv->remain_on_ch_params.listen_duration = duration;
-       priv->p2p_listen_state = true;
-
+       vif->p2p_listen_state = true;
        cfg80211_ready_on_channel(wdev, *cookie, chan, duration, GFP_KERNEL);
 
 #if KERNEL_VERSION(4, 15, 0) > LINUX_VERSION_CODE
        vif->hif_drv->remain_on_ch_timer.data = (unsigned long)vif->hif_drv;
 #endif
        mod_timer(&vif->hif_drv->remain_on_ch_timer,
-                 jiffies + msecs_to_jiffies(duration));
+                 jiffies + msecs_to_jiffies(duration + 1000));
 
        PRINT_INFO(vif->ndev, GENERIC_DBG,
                   "Remaining on duration [%d] [%llu]\n",
                   duration, priv->remain_on_ch_params.listen_cookie);
-
        return ret;
 }
 
@@ -1358,8 +1406,8 @@ static int cancel_remain_on_channel(struct wiphy *wiphy,
                                    struct wireless_dev *wdev,
                                    u64 cookie)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc_vif *vif = netdev_priv(wdev->netdev);
+       struct wilc_priv *priv = &vif->priv;
 
        PRINT_INFO(vif->ndev, CFG80211_DBG,
                   "cookie received[%llu] expected[%llu]\n",
@@ -1410,6 +1458,7 @@ static void wilc_wfi_cfg_tx_vendor_spec(struct wilc_priv *priv,
                if (buf[i] == P2PELEM_ATTR_ID &&
                    !memcmp(p2p_oui, &buf[i + 2], 4)) {
                        bool oper_ch = false;
+                       struct wilc *wl = vif->wilc;
                        u8 *tx_buff = &mgmt_tx->buff[i + 6];
 
                        if (subtype == P2P_INV_REQ || subtype == P2P_INV_RSP)
@@ -1417,8 +1466,8 @@ static void wilc_wfi_cfg_tx_vendor_spec(struct wilc_priv *priv,
 
                        wilc_wfi_cfg_parse_tx_action(vif, tx_buff,
                                                     len - (i + 6), oper_ch,
-                                                    vif->wilc->sta_ch,
-                                                    vif->attr_sysfs.p2p_mode);
+                                                    wl->sta_ch,
+                                                    wl->attr_sysfs.p2p_mode);
                        break;
                }
        }
@@ -1454,9 +1503,9 @@ static int mgmt_tx(struct wiphy *wiphy,
 #endif
        const struct ieee80211_mgmt *mgmt;
        struct wilc_p2p_mgmt_data *mgmt_tx;
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct host_if_drv *wfi_drv = priv->hif_drv;
        struct wilc_vif *vif = netdev_priv(wdev->netdev);
+       struct wilc_priv *priv = &vif->priv;
+       struct host_if_drv *wfi_drv = priv->hif_drv;
        u32 buf_len = len + sizeof(p2p_vendor_spec) +
                      sizeof(priv->p2p.local_random);
        int ret = 0;
@@ -1552,7 +1601,6 @@ static int mgmt_tx(struct wiphy *wiphy,
                        break;
                }
        }
-
        PRINT_INFO(vif->ndev, GENERIC_DBG,
                   "TX: ACTION FRAME Type:%x : Chan:%d\n",
                   buf[ACTION_SUBTYPE_ID], chan->hw_value);
@@ -1560,7 +1608,8 @@ static int mgmt_tx(struct wiphy *wiphy,
 
 out_txq_add_pkt:
 
-       txq_add_mgmt_pkt(wdev->netdev, mgmt_tx,  mgmt_tx->buff, mgmt_tx->size,
+       txq_add_mgmt_pkt(priv->wdev.netdev, mgmt_tx,
+                        mgmt_tx->buff, mgmt_tx->size,
                         wilc_wfi_mgmt_tx_complete);
 
 out:
@@ -1572,17 +1621,18 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
                               struct wireless_dev *wdev,
                               u64 cookie)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
+       struct wilc_vif *vif = netdev_priv(wdev->netdev);
+       struct wilc_priv *priv = &vif->priv;
        struct host_if_drv *wfi_drv = priv->hif_drv;
 
        wfi_drv->p2p_timeout = jiffies;
 
-       if (!priv->p2p_listen_state) {
+       if (!vif->p2p_listen_state) {
                struct wilc_wfi_p2p_listen_params *params;
 
                params = &priv->remain_on_ch_params;
 
-               cfg80211_remain_on_channel_expired(priv->wdev,
+               cfg80211_remain_on_channel_expired(wdev,
                                                   params->listen_cookie,
                                                   params->listen_ch,
                                                   GFP_KERNEL);
@@ -1594,14 +1644,13 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy,
 void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
                              u16 frame_type, bool reg)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->wdev->netdev);
-       struct wilc *wl = vif->wilc;
+       struct wilc *wl = wiphy_priv(wiphy);
+       struct wilc_vif *vif = netdev_priv(wdev->netdev);
 
        if (!frame_type)
                return;
 
-       PRINT_INFO(vif->ndev, GENERIC_DBG,
+       PRINT_D(vif->ndev, GENERIC_DBG,
                   "Frame registering Frame Type: %x: Boolean: %d\n",
                   frame_type, reg);
        switch (frame_type) {
@@ -1637,8 +1686,7 @@ static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev,
 static int dump_station(struct wiphy *wiphy, struct net_device *dev,
                        int idx, u8 *mac, struct station_info *sinfo)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc_vif *vif = netdev_priv(dev);
        int ret;
 
        if (idx != 0)
@@ -1662,28 +1710,15 @@ static int dump_station(struct wiphy *wiphy, struct net_device *dev,
 static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
                          bool enabled, int timeout)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc_vif *vif = netdev_priv(dev);
+       struct wilc_priv *priv = &vif->priv;
 
+       PRINT_INFO(vif->ndev, GENERIC_DBG, "dev [%s]\n", dev->name);
        if (!priv->hif_drv) {
                PRINT_ER(dev, "hif driver is NULL\n");
                return -EIO;
        }
 
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-       /* Can't set PS during obtaining IP */
-       if (vif->obtaining_ip == true) {
-               PRINT_ER(dev,
-                        "Device obtaining IP, Power Managment will be handled after IP Obtained\n");
-               PRINT_INFO(vif->ndev, GENERIC_DBG,
-                          "Save the Current state of the PS = %d\n", enabled);
-
-               /* Save the current status of the PS */
-               store_power_save_current_state(vif, enabled);
-
-               return 0;
-       }
-#endif
        PRINT_INFO(vif->ndev, CFG80211_DBG,
                   " Power save Enabled= %d , TimeOut = %d\n", enabled,
                   timeout);
@@ -1703,13 +1738,9 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
                               struct vif_params *params)
 #endif
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
+       struct wilc *wl = wiphy_priv(wiphy);
        struct wilc_vif *vif = netdev_priv(dev);
-       struct wilc *wl = vif->wilc;
-       struct net_device *net_device_1 = wilc_get_if_netdev(wl, WILC_P2P_IFC);
-       struct net_device *net_device_2 = wilc_get_if_netdev(wl, WILC_WLAN_IFC);
-       struct wilc_vif *vif_1 = netdev_priv(net_device_1);
-       struct wilc_vif *vif_2 = netdev_priv(net_device_2);
+       struct wilc_priv *priv = &vif->priv;
 
        PRINT_INFO(vif->ndev, HOSTAPD_DBG,
                   "In Change virtual interface function\n");
@@ -1718,11 +1749,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
        priv->p2p.local_random = 0x01;
        priv->p2p.recv_random = 0x00;
        priv->p2p.is_wilc_ie = false;
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                  "Changing virtual interface, enable scan\n");
-       handle_pwrsave_for_IP(vif, IP_STATE_DEFAULT);
-#endif
 
        switch (type) {
        case NL80211_IFTYPE_STATION:
@@ -1730,18 +1756,18 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
                PRINT_INFO(vif->ndev, HOSTAPD_DBG,
                           "Interface type = NL80211_IFTYPE_STATION\n");
                dev->ieee80211_ptr->iftype = type;
-               priv->wdev->iftype = type;
+               priv->wdev.iftype = type;
                vif->monitor_flag = 0;
+               if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE)
+                       wilc_wfi_deinit_mon_interface(wl, true);
                vif->iftype = WILC_STATION_MODE;
-               wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
-                                        WILC_STATION_MODE, vif->ifc_id);
-               wilc_set_operation_mode(vif, WILC_STATION_MODE);
+
+               if (wl->initialized)
+                       wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),
+                                               WILC_STATION_MODE, vif->idx);
 
                memset(priv->assoc_stainfo.sta_associated_bss, 0,
                       WILC_MAX_NUM_STA * ETH_ALEN);
-
-               wilc_set_power_mgmt(vif_1, 1, 0);
-               wilc_set_power_mgmt(vif_2, 1, 0);
                break;
 
        case NL80211_IFTYPE_P2P_CLIENT:
@@ -1749,30 +1775,25 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
                PRINT_INFO(vif->ndev, HOSTAPD_DBG,
                           "Interface type = NL80211_IFTYPE_P2P_CLIENT\n");
                dev->ieee80211_ptr->iftype = type;
-               priv->wdev->iftype = type;
+               priv->wdev.iftype = type;
                vif->monitor_flag = 0;
                vif->iftype = WILC_CLIENT_MODE;
-               wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
-                                        WILC_STATION_MODE, vif->ifc_id);
-               wilc_set_operation_mode(vif, WILC_STATION_MODE);
 
-               wilc_set_power_mgmt(vif_1, 0, 0);
-               wilc_set_power_mgmt(vif_2, 0, 0);
+               if (wl->initialized)
+                       wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),
+                                               WILC_STATION_MODE, vif->idx);
                break;
 
        case NL80211_IFTYPE_AP:
                PRINT_INFO(vif->ndev, HOSTAPD_DBG,
                           "Interface type = NL80211_IFTYPE_AP\n");
                dev->ieee80211_ptr->iftype = type;
-               priv->wdev->iftype = type;
+               priv->wdev.iftype = type;
                vif->iftype = WILC_AP_MODE;
-               if (wl->initialized) {
-                       wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
-                                                WILC_AP_MODE, vif->ifc_id);
-                       wilc_set_operation_mode(vif, WILC_AP_MODE);
-                       wilc_set_power_mgmt(vif_1, 0, 0);
-                       wilc_set_power_mgmt(vif_2, 0, 0);
-               }
+
+               if (wl->initialized)
+                       wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),
+                                                WILC_AP_MODE, vif->idx);
                break;
 
        case NL80211_IFTYPE_P2P_GO:
@@ -1780,34 +1801,26 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
                           "Interface type = NL80211_IFTYPE_GO\n");
                PRINT_INFO(vif->ndev, GENERIC_DBG, "start duringIP timer\n");
 
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-               handle_pwrsave_for_IP(vif, IP_STATE_GO_ASSIGNING);
-#endif
                dev->ieee80211_ptr->iftype = type;
-               priv->wdev->iftype = type;
+               priv->wdev.iftype = type;
                vif->iftype = WILC_GO_MODE;
-               wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
-                                       WILC_AP_MODE, vif->ifc_id);
-               wilc_set_operation_mode(vif, WILC_AP_MODE);
-               wilc_set_power_mgmt(vif_1, 0, 0);
-               wilc_set_power_mgmt(vif_2, 0, 0);
+
+               if (wl->initialized)
+                       wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),
+                                               WILC_AP_MODE, vif->idx);
                break;
        case NL80211_IFTYPE_MONITOR:
                PRINT_INFO(vif->ndev, HOSTAPD_DBG,
                           "Interface type = NL80211_IFTYPE_MONITOR\n");
                dev->ieee80211_ptr->iftype = type;
                dev->type = ARPHRD_IEEE80211_RADIOTAP;
-               priv->wdev->iftype = type;
+               priv->wdev.iftype = type;
                vif->iftype = WILC_MONITOR_MODE;
-               if (wl->initialized) {
-                       wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
-                                                WILC_MONITOR_MODE,
-                                                vif->ifc_id);
 
-                       wilc_set_operation_mode(vif, WILC_MONITOR_MODE);
-                       wilc_set_power_mgmt(vif_1, 0, 0);
-                       wilc_set_power_mgmt(vif_2, 0, 0);
-               }
+               if (wl->initialized)
+                       wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),
+                                                WILC_MONITOR_MODE,
+                                                vif->idx);
                break;
 
        default:
@@ -1821,22 +1834,25 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,
 static int start_ap(struct wiphy *wiphy, struct net_device *dev,
                    struct cfg80211_ap_settings *settings)
 {
-       struct wilc_vif *vif = netdev_priv(dev);
        int ret;
+       struct wilc_vif *vif = netdev_priv(dev);
+       int freq = settings->chandef.chan->center_freq;
+       int channelnum = ieee80211_frequency_to_channel(freq);
+
+       pr_info("%s,dev[%s]\n", __func__, dev->name);
 
        PRINT_INFO(vif->ndev, HOSTAPD_DBG, "Starting ap\n");
 
        PRINT_INFO(vif->ndev, CFG80211_DBG,
-                  "Interval= %d\n DTIM period= %d\n Head length= %d Tail length= %d\n",
+                  "Interval= %d\n DTIM period= %d\n Head length= %d Tail length= %d channelnum[%d]\n",
                   settings->beacon_interval, settings->dtim_period,
-                  settings->beacon.head_len, settings->beacon.tail_len);
-       ret = set_channel(wiphy, &settings->chandef);
-
+                  settings->beacon.head_len, settings->beacon.tail_len,
+                  channelnum);
+       ret = wilc_set_mac_chnl_num(vif, channelnum);
        if (ret != 0)
                PRINT_ER(dev, "Error in setting channel\n");
 
        wilc_wlan_set_bssid(dev, dev->dev_addr, WILC_AP_MODE);
-       wilc_set_power_mgmt(vif, 0, 0);
 
        return wilc_add_beacon(vif, settings->beacon_interval,
                               settings->dtim_period, &settings->beacon);
@@ -1845,8 +1861,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev,
 static int change_beacon(struct wiphy *wiphy, struct net_device *dev,
                         struct cfg80211_beacon_data *beacon)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc_vif *vif = netdev_priv(dev);
 
        PRINT_INFO(vif->ndev, HOSTAPD_DBG, "Setting beacon\n");
 
@@ -1856,8 +1871,7 @@ static int change_beacon(struct wiphy *wiphy, struct net_device *dev,
 static int stop_ap(struct wiphy *wiphy, struct net_device *dev)
 {
        int ret;
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc_vif *vif = netdev_priv(dev);
 
        PRINT_INFO(vif->ndev, CFG80211_DBG, "Deleting beacon\n");
 
@@ -1867,7 +1881,6 @@ static int stop_ap(struct wiphy *wiphy, struct net_device *dev)
 
        if (ret)
                PRINT_ER(dev, "Host delete beacon fail\n");
-
        return ret;
 }
 
@@ -1880,8 +1893,8 @@ static int add_station(struct wiphy *wiphy, struct net_device *dev,
 #endif
 {
        int ret = 0;
-       struct wilc_priv *priv = wiphy_priv(wiphy);
        struct wilc_vif *vif = netdev_priv(dev);
+       struct wilc_priv *priv = &vif->priv;
        u8 *assoc_bss = priv->assoc_stainfo.sta_associated_bss[params->aid];
 
        if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE) {
@@ -1946,8 +1959,8 @@ static int del_station(struct wiphy *wiphy, struct net_device *dev,
        const u8 *mac = params->mac;
 #endif
        int ret = 0;
-       struct wilc_priv *priv = wiphy_priv(wiphy);
        struct wilc_vif *vif = netdev_priv(dev);
+       struct wilc_priv *priv = &vif->priv;
        struct sta_info *info;
 
        if (!(vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE))
@@ -2025,6 +2038,17 @@ static int change_station(struct wiphy *wiphy, struct net_device *dev,
        return ret;
 }
 
+struct wilc_vif *wilc_get_vif_from_type(struct wilc *wl, int type)
+{
+       struct wilc_vif *vif;
+
+       list_for_each_entry_rcu(vif, &wl->vif_list, list) {
+               if (vif->iftype == type)
+                       return vif;
+       }
+       return NULL;
+}
+
 #if KERNEL_VERSION(4, 12, 0) <= LINUX_VERSION_CODE
 static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,
                                             const char *name,
@@ -2052,80 +2076,161 @@ static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,
                                             struct vif_params *params)
 #endif
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->wdev->netdev);
-       struct net_device *new_ifc;
-
-       PRINT_INFO(vif->ndev, CFG80211_DBG, "Adding monitor interface[%p]\n",
-                  priv->wdev->netdev);
+       struct wilc *wl = wiphy_priv(wiphy);
+       struct wilc_vif *vif;
+       struct wireless_dev *wdev;
+       u8 iftype;
 
+       /* check if interface type is mointor because AP mode is supported over
+        * monitor interface. No need to increment interface count check if
+        * monitor mode is associated with AP interface. The same approach is
+        * applied with p2p_device interface
+        */
        if (type == NL80211_IFTYPE_MONITOR) {
+               struct wilc_vif *vif;
+               struct net_device *ndev;
+               int srcu_idx;
+
+               srcu_idx = srcu_read_lock(&wl->srcu);
+               vif = wilc_get_vif_from_type(wl, WILC_AP_MODE);
+
+               if (!vif) {
+                       vif = wilc_get_vif_from_type(wl, WILC_GO_MODE);
+                       if (!vif) {
+                               srcu_read_unlock(&wl->srcu, srcu_idx);
+                               goto validate_interface;
+                       }
+               }
+
+               if (vif->monitor_flag) {
+                       srcu_read_unlock(&wl->srcu, srcu_idx);
+                       goto validate_interface;
+               }
                PRINT_INFO(vif->ndev, CFG80211_DBG,
                           "Initializing mon ifc virtual device driver\n");
                PRINT_INFO(vif->ndev, CFG80211_DBG,
                           "Adding monitor interface[%p]\n", vif->ndev);
-               new_ifc = wilc_wfi_init_mon_interface(vif->wilc, name,
-                                                     vif->ndev);
-               if (new_ifc) {
+               ndev = wilc_wfi_init_mon_interface(vif->wilc, name, vif->ndev);
+               if (ndev) {
                        PRINT_INFO(vif->ndev, CFG80211_DBG,
                        "Setting monitor flag in private structure\n");
-                       vif = netdev_priv(priv->wdev->netdev);
                        vif->monitor_flag = 1;
                } else {
                        PRINT_ER(vif->ndev,
                                 "Error in initializing monitor interface\n");
                }
+               wdev = &vif->priv.wdev;
+               srcu_read_unlock(&wl->srcu, srcu_idx);
+               return wdev;
+       }
+
+validate_interface:
+       mutex_lock(&wl->vif_mutex);
+       if (wl->vif_num == WILC_NUM_CONCURRENT_IFC) {
+               pr_err("Reached maximum number of supported vif\n");
+               mutex_unlock(&wl->vif_mutex);
+               return ERR_PTR(-EINVAL);
+       }
+       mutex_unlock(&wl->vif_mutex);
+
+       pr_info("add_interaface [%d] name[%s] type[%d]\n", wl->vif_num,
+              name, type);
+
+       switch (type) {
+       case NL80211_IFTYPE_STATION:
+               iftype = WILC_STATION_MODE;
+               break;
+       case NL80211_IFTYPE_AP:
+               iftype = WILC_AP_MODE;
+               break;
+       case NL80211_IFTYPE_MONITOR:
+               iftype = WILC_MONITOR_MODE;
+               break;
+       default:
+               return ERR_PTR(-EINVAL);
        }
-       return priv->wdev;
+
+       vif = wilc_netdev_ifc_init(wl, name, iftype, type, true);
+       if (IS_ERR(vif))
+               return ERR_PTR(-EINVAL);
+
+       return &vif->priv.wdev;
 }
 
 static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
+       struct wilc *wl = wiphy_priv(wiphy);
+       struct wilc_vif *vif;
 
-       PRINT_INFO(priv->dev, HOSTAPD_DBG, "Deleting virtual interface\n");
+       /* delete the monitor mode interface */
+       if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
+               wilc_wfi_deinit_mon_interface(wl, true);
+               return 0;
+       }
+       /* delete the AP monitor mode interface */
+       if (wdev->iftype == NL80211_IFTYPE_AP ||
+           wdev->iftype == NL80211_IFTYPE_P2P_GO)
+               wilc_wfi_deinit_mon_interface(wl, true);
+       vif = netdev_priv(wdev->netdev);
+       unregister_netdevice(vif->ndev);
+       vif->monitor_flag = 0;
+
+       /* update the vif list */
+       mutex_lock(&wl->vif_mutex);
+       //delete the interface from rcu list
+       list_del_rcu(&vif->list);
+       wl->vif_num--;
+       mutex_unlock(&wl->vif_mutex);
+       synchronize_srcu(&wl->srcu);
        return 0;
 }
 
 static int wilc_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-
-       if (!wow)
-               PRINT_INFO(priv->dev, GENERIC_DBG,
-                          "No wake up triggers defined\n");
-       else if (wow->any == 0)
-               PRINT_INFO(priv->dev, GENERIC_DBG,
-                          "The only supported wake up trigger (any) is not set\n");
-
        return 0;
 }
 
 static int wilc_resume(struct wiphy *wiphy)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
-
-       PRINT_INFO(vif->ndev, GENERIC_DBG, "cfg resume\n");
        return 0;
 }
 
 static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled)
 {
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc *wl = wiphy_priv(wiphy);
+       struct wilc_vif *vif;
+       int srcu_idx;
+
+       srcu_idx = srcu_read_lock(&wl->srcu);
+       vif = wilc_get_wl_to_vif(wl);
+       if (IS_ERR(vif)) {
+               srcu_read_unlock(&wl->srcu, srcu_idx);
+               return;
+       }
 
        PRINT_INFO(vif->ndev, GENERIC_DBG, "cfg set wake up = %d\n", enabled);
        wilc_set_wowlan_trigger(vif, (u8)enabled);
+       srcu_read_unlock(&wl->srcu, srcu_idx);
 }
 
 static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
                        enum nl80211_tx_power_setting type, int mbm)
 {
        int ret;
+       int srcu_idx;
        s32 tx_power = MBM_TO_DBM(mbm);
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc *wl = wiphy_priv(wiphy);
+       struct wilc_vif *vif;
+
+       if (!wl->initialized)
+               return -EIO;
+
+       srcu_idx = srcu_read_lock(&wl->srcu);
+       vif = wilc_get_wl_to_vif(wl);
+       if (IS_ERR(vif)) {
+               srcu_read_unlock(&wl->srcu, srcu_idx);
+               return -EINVAL;
+       }
 
        PRINT_INFO(vif->ndev, CFG80211_DBG, "Setting tx power %d\n", tx_power);
        if (tx_power < 0)
@@ -2136,6 +2241,8 @@ static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
        if (ret)
                PRINT_ER(vif->ndev, "Failed to set tx power\n");
 
+       srcu_read_unlock(&wl->srcu, srcu_idx);
+
        return ret;
 }
 
@@ -2143,8 +2250,7 @@ static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
                        int *dbm)
 {
        int ret;
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc_vif *vif = netdev_priv(wdev->netdev);
        struct wilc *wl = vif->wilc;
 
        /* If firmware is not started, return. */
@@ -2163,16 +2269,27 @@ static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
 static int set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
 {
        int ret;
-       struct wilc_priv *priv = wiphy_priv(wiphy);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc *wl = wiphy_priv(wiphy);
+       struct wilc_vif *vif;
+       int srcu_idx;
+
+       srcu_idx = srcu_read_lock(&wl->srcu);
+       vif = wilc_get_wl_to_vif(wl);
+       if (IS_ERR(vif)) {
+               srcu_read_unlock(&wl->srcu, srcu_idx);
+               return -EINVAL;
+       }
 
        PRINT_INFO(vif->ndev, CFG80211_DBG, "Select antenna mode %d\n", tx_ant);
-       if (!tx_ant || !rx_ant)
+       if (!tx_ant || !rx_ant) {
+               srcu_read_unlock(&wl->srcu, srcu_idx);
                return -EINVAL;
+       }
 
        ret = wilc_set_antenna(vif, (u8)(tx_ant-1));
        if (ret)
                PRINT_ER(vif->ndev, "Failed to set tx antenna\n");
+       srcu_read_unlock(&wl->srcu, srcu_idx);
 
        return ret;
 }
@@ -2220,136 +2337,185 @@ static const struct cfg80211_ops wilc_cfg80211_ops = {
        .set_antenna = set_antenna,
 };
 
-static struct wireless_dev *wilc_wfi_cfg_alloc(struct net_device *net)
+static void wlan_init_locks(struct wilc *wl)
 {
-       struct wireless_dev *wdev;
+       pr_info("Initializing Locks ...\n");
+       mutex_init(&wl->vif_mutex);
+       mutex_init(&wl->rxq_cs);
+       mutex_init(&wl->cfg_cmd_lock);
+       mutex_init(&wl->deinit_lock);
+       mutex_init(&wl->hif_cs);
+       mutex_init(&wl->cs);
+
+       spin_lock_init(&wl->txq_spinlock);
+       mutex_init(&wl->txq_add_to_head_cs);
+
+       init_completion(&wl->txq_event);
+
+       init_completion(&wl->cfg_event);
+       init_completion(&wl->sync_event);
+       init_completion(&wl->txq_thread_started);
+       init_completion(&wl->debug_thread_started);
+       init_srcu_struct(&wl->srcu);
+}
 
-       PRINT_INFO(net, CFG80211_DBG, "Allocating wireless device\n");
-       wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
-       if (!wdev) {
-               PRINT_ER(net, "Cannot allocate wireless device\n");
-               goto out;
+void wlan_deinit_locks(struct wilc *wl)
+{
+       pr_info("De-Initializing Locks\n");
+       mutex_destroy(&wl->hif_cs);
+       mutex_destroy(&wl->rxq_cs);
+       mutex_destroy(&wl->cfg_cmd_lock);
+       mutex_destroy(&wl->vif_mutex);
+       mutex_destroy(&wl->txq_add_to_head_cs);
+       mutex_destroy(&wl->cs);
+       mutex_destroy(&wl->deinit_lock);
+       cleanup_srcu_struct(&wl->srcu);
+}
+
+int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
+                      const struct wilc_hif_func *ops)
+{
+       int i, ret;
+       struct wilc *wl;
+       struct wilc_vif *vif;
+
+       wl = wilc_create_wiphy(dev);
+       if (!wl) {
+               pr_err("failed to create wiphy\n");
+               return -EINVAL;
        }
 
-       wdev->wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc_priv));
-       if (!wdev->wiphy) {
-               PRINT_ER(net, "Cannot allocate wiphy\n");
-               goto free_mem;
+       wlan_init_locks(wl);
+
+       ret = cfg_init(wl);
+       if (ret)
+               goto free_wl;
+
+       wilc_debugfs_init();
+       *wilc = wl;
+       wl->io_type = io_type;
+       wl->hif_func = ops;
+       for (i = 0; i < NQUEUES; i++)
+               INIT_LIST_HEAD(&wl->txq[i].txq_head.list);
+
+       INIT_LIST_HEAD(&wl->rxq_head.list);
+       INIT_LIST_HEAD(&wl->vif_list);
+
+       wl->hif_workqueue = create_singlethread_workqueue("WILC_wq");
+       if (!wl->hif_workqueue) {
+               ret = -ENOMEM;
+               goto free_debug_fs;
+       }
+       vif = wilc_netdev_ifc_init(wl, "wlan%d", WILC_STATION_MODE,
+                                  NL80211_IFTYPE_STATION, false);
+       if (IS_ERR(vif)) {
+               ret = PTR_ERR(vif);
+               goto free_wq;
        }
 
-       return wdev;
+       wilc_sysfs_init(wl);
 
-free_mem:
-       kfree(wdev);
-out:
-       return NULL;
+       return 0;
+free_wq:
+       destroy_workqueue(wl->hif_workqueue);
+free_debug_fs:
+       wilc_debugfs_remove();
+       cfg_deinit(wl);
+free_wl:
+       wlan_deinit_locks(wl);
+       wiphy_unregister(wl->wiphy);
+       wiphy_free(wl->wiphy);
+       return ret;
 }
 
-struct wireless_dev *wilc_create_wiphy(struct net_device *net,
-                                      struct device *dev)
+struct wilc *wilc_create_wiphy(struct device *dev)
 {
-       struct wilc_priv *priv;
-       struct wireless_dev *wdev;
+       struct wiphy *wiphy;
+       struct wilc *wl;
        int ret;
 
-       PRINT_INFO(net, CFG80211_DBG, "Registering wifi device\n");
-       wdev = wilc_wfi_cfg_alloc(net);
-       if (!wdev) {
-               PRINT_ER(net, "wiphy new allocate failed\n");
-               return NULL;
+       wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc));
+       if (!wiphy) {
+               pr_err("wiphy new allocate failed\n");
+               return ERR_PTR(-EFAULT);
        }
 
-       priv = wdev_priv(wdev);
-       priv->wdev = wdev;
+       wl = wiphy_priv(wiphy);
+       pr_info("Registering wifi device\n");
 
-       memcpy(priv->bitrates, wilc_bitrates, sizeof(wilc_bitrates));
-       memcpy(priv->channels, wilc_2ghz_channels, sizeof(wilc_2ghz_channels));
-       priv->band.bitrates = priv->bitrates;
-       priv->band.n_bitrates = ARRAY_SIZE(priv->bitrates);
-       priv->band.channels = priv->channels;
-       priv->band.n_channels = ARRAY_SIZE(wilc_2ghz_channels);
+       memcpy(wl->bitrates, wilc_bitrates, sizeof(wilc_bitrates));
+       memcpy(wl->channels, wilc_2ghz_channels, sizeof(wilc_2ghz_channels));
+       wl->band.bitrates = wl->bitrates;
+       wl->band.n_bitrates = ARRAY_SIZE(wl->bitrates);
+       wl->band.channels = wl->channels;
+       wl->band.n_channels = ARRAY_SIZE(wilc_2ghz_channels);
 
-       priv->band.ht_cap.ht_supported = 1;
-       priv->band.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
-       priv->band.ht_cap.mcs.rx_mask[0] = 0xff;
-       priv->band.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
-       priv->band.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
+       wl->band.ht_cap.ht_supported = 1;
+       wl->band.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
+       wl->band.ht_cap.mcs.rx_mask[0] = 0xff;
+       wl->band.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;
+       wl->band.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
 
 #if KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE
-       wdev->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band;
+       wiphy->bands[NL80211_BAND_2GHZ] = &wl->band;
 #else
-       wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
+       wiphy->bands[IEEE80211_BAND_2GHZ] = &wl->band;
 #endif
 
-       wdev->wiphy->max_scan_ssids = WILC_MAX_NUM_PROBED_SSID;
+       wiphy->max_scan_ssids = WILC_MAX_NUM_PROBED_SSID;
 #if KERNEL_VERSION(3, 11, 0) <= LINUX_VERSION_CODE
-       wdev->wiphy->wowlan = &wowlan_support;
+       wiphy->wowlan = &wowlan_support;
 #else
-       wdev->wiphy->wowlan = wowlan_support;
+       wiphy->wowlan = wowlan_support;
 #endif
-       wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;
-       PRINT_D(net, CFG80211_DBG, "Max number of PMKIDs = %d\n",
-               wdev->wiphy->max_num_pmkids);
-       wdev->wiphy->max_scan_ie_len = 1000;
-       wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
-       memcpy(priv->cipher_suites, wilc_cipher_suites,
+       wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;
+       wiphy->max_scan_ie_len = 1000;
+       wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+       memcpy(wl->cipher_suites, wilc_cipher_suites,
               sizeof(wilc_cipher_suites));
-       wdev->wiphy->cipher_suites = priv->cipher_suites;
-       wdev->wiphy->n_cipher_suites = ARRAY_SIZE(wilc_cipher_suites);
-       wdev->wiphy->available_antennas_tx = 0x3;
-       wdev->wiphy->available_antennas_rx = 0x3;
-       wdev->wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;
-
-       wdev->wiphy->max_remain_on_channel_duration = 500;
-       wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+       wiphy->cipher_suites = wl->cipher_suites;
+       wiphy->n_cipher_suites = ARRAY_SIZE(wilc_cipher_suites);
+       wiphy->available_antennas_tx = 0x3;
+       wiphy->available_antennas_rx = 0x3;
+       wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;
+
+       wiphy->max_remain_on_channel_duration = 500;
+       wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
                                        BIT(NL80211_IFTYPE_AP) |
                                        BIT(NL80211_IFTYPE_MONITOR) |
                                        BIT(NL80211_IFTYPE_P2P_GO) |
                                        BIT(NL80211_IFTYPE_P2P_CLIENT);
-       wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
-       wdev->iftype = NL80211_IFTYPE_STATION;
-
-       PRINT_D(net, CFG80211_DBG,
-               "Max scan ids= %d,Max scan IE len= %d,Signal Type= %d,Interface Modes= %d,Interface Type= %d\n",
-               wdev->wiphy->max_scan_ssids, wdev->wiphy->max_scan_ie_len,
-               wdev->wiphy->signal_type, wdev->wiphy->interface_modes,
-               wdev->iftype);
-
-       set_wiphy_dev(wdev->wiphy, dev);
-
-       ret = wiphy_register(wdev->wiphy);
+       wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+       pr_info("Max scan ids= %d,Max scan IE len= %d,Signal Type= %d,Interface Modes= %d\n",
+               wiphy->max_scan_ssids, wiphy->max_scan_ie_len,
+               wiphy->signal_type, wiphy->interface_modes);
+
+       set_wiphy_dev(wiphy, dev);
+       wl->wiphy = wiphy;
+       ret = wiphy_register(wiphy);
        if (ret) {
-               PRINT_ER(net, "Cannot register wiphy device\n");
-               wiphy_free(wdev->wiphy);
-               kfree(wdev);
-               return NULL;
+               pr_err("Cannot register wiphy device\n");
+               wiphy_free(wiphy);
+               return ERR_PTR(-EFAULT);
        }
-
-       priv->dev = net;
-       return wdev;
+       return wl;
 }
 
 int wilc_init_host_int(struct net_device *net)
 {
        int ret;
-       struct wilc_priv *priv = wdev_priv(net->ieee80211_ptr);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc_vif *vif = netdev_priv(net);
+       struct wilc_priv *priv = &vif->priv;
 
        PRINT_INFO(net, INIT_DBG, "Host[%p][%p]\n", net, net->ieee80211_ptr);
 
 #if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
-       #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-       timer_setup(&vif->during_ip_timer, clear_during_ip, 0);
-       #endif
        timer_setup(&priv->eap_buff_timer, eap_buff_timeout, 0);
 #else
-       #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-       setup_timer(&vif->during_ip_timer, clear_during_ip, 0);
-       #endif
        setup_timer(&priv->eap_buff_timer, eap_buff_timeout, 0);
 #endif
 
-       priv->p2p_listen_state = false;
+       vif->p2p_listen_state = false;
 
        mutex_init(&priv->scan_req_lock);
        ret = wilc_init(net, &priv->hif_drv);
@@ -2362,17 +2528,15 @@ int wilc_init_host_int(struct net_device *net)
 void wilc_deinit_host_int(struct net_device *net)
 {
        int ret;
-       struct wilc_priv *priv = wdev_priv(net->ieee80211_ptr);
-       struct wilc_vif *vif = netdev_priv(priv->dev);
+       struct wilc_vif *vif = netdev_priv(net);
+       struct wilc_priv *priv = &vif->priv;
 
-       priv->p2p_listen_state = false;
+       vif->p2p_listen_state = false;
 
+       flush_workqueue(vif->wilc->hif_workqueue);
        mutex_destroy(&priv->scan_req_lock);
        ret = wilc_deinit(vif);
 
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-       del_timer_sync(&vif->during_ip_timer);
-#endif
        del_timer_sync(&priv->eap_buff_timer);
 
        if (ret)
index 9c56c4d..a31dfae 100644 (file)
@@ -8,18 +8,22 @@
 #define NM_WFI_CFGOPERATIONS
 #include "wilc_wfi_netdevice.h"
 
-struct wireless_dev *wilc_create_wiphy(struct net_device *net,
-                                      struct device *dev);
+struct wilc *wilc_create_wiphy(struct device *dev);
 void wilc_free_wiphy(struct net_device *net);
 void wilc_deinit_host_int(struct net_device *net);
 int wilc_init_host_int(struct net_device *net);
 void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size);
-void wilc_wfi_deinit_mon_interface(struct wilc *wl);
+void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked);
 struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
                                               const char *name,
                                               struct net_device *real_dev);
 void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev,
                              u16 frame_type, bool reg);
-void wilc_sysfs_init(struct wilc_vif *vif1, struct wilc_vif *vif2);
+void wilc_sysfs_init(struct wilc *wilc);
 void wilc_sysfs_exit(void);
+int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
+                      const struct wilc_hif_func *ops);
+struct wilc_vif *wilc_get_vif_from_type(struct wilc *wl, int type);
+struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl);
+void wlan_deinit_locks(struct wilc *wl);
 #endif
index 0380c6d..00409f9 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/gpio.h>
 #endif
 
-#include "host_interface.h"
+#include "wilc_hif.h"
 #include "wilc_wlan.h"
 #include "wilc_wlan_cfg.h"
 
@@ -156,7 +156,7 @@ static struct ieee80211_rate wilc_bitrates[] = {
 };
 
 struct wilc_priv {
-       struct wireless_dev *wdev;
+       struct wireless_dev wdev;
        struct cfg80211_scan_request *scan_req;
        struct wilc_wfi_p2p_listen_params remain_on_ch_params;
        u64 tx_cookie;
@@ -164,7 +164,7 @@ struct wilc_priv {
        u8 associated_bss[ETH_ALEN];
        struct sta_info assoc_stainfo;
        struct sk_buff *skb;
-       struct net_device *dev;
+       struct net_device *dev; //TODO:need to remove it
        struct host_if_drv *hif_drv;
        struct wilc_pmkid_attr pmkid_list;
        u8 wep_key[4][WLAN_KEY_LEN_WEP104];
@@ -177,16 +177,11 @@ struct wilc_priv {
 
        struct mutex scan_req_lock;
 
-       bool p2p_listen_state;
        struct wilc_buffered_eap *buffered_eap;
 
        struct timer_list eap_buff_timer;
        int scanned_cnt;
        struct wilc_p2p_var p2p;
-       struct ieee80211_channel channels[ARRAY_SIZE(wilc_2ghz_channels)];
-       struct ieee80211_rate bitrates[ARRAY_SIZE(wilc_bitrates)];
-       struct ieee80211_supported_band band;
-       u32 cipher_suites[ARRAY_SIZE(wilc_cipher_suites)];
        u64 inc_roc_cookie;
 };
 
@@ -239,21 +234,20 @@ struct wilc_vif {
        u8 bssid[ETH_ALEN];
        struct host_if_drv *hif_drv;
        struct net_device *ndev;
-       u8 ifc_id;
 
-       struct sysfs_attr_group attr_sysfs;
-#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-       bool pwrsave_current_state;
-       struct timer_list during_ip_timer;
-       bool obtaining_ip;
-#endif
        struct rf_info periodic_stats;
        struct timer_list periodic_rssi;
        struct tcp_ack_filter ack_filter;
        bool connecting;
+       struct wilc_priv priv;
+       struct list_head list;
+       u8 restart;
+       bool p2p_listen_state;
+       struct cfg80211_bss *bss;
 };
 
 struct wilc {
+       struct wiphy *wiphy;
        const struct wilc_hif_func *hif_func;
        int io_type;
        s8 mac_status;
@@ -262,11 +256,15 @@ struct wilc {
 #else
        int gpio_irq;
 #endif
+       struct clk *rtc_clk;
        bool initialized;
        int dev_irq_num;
        int close;
        u8 vif_num;
-       struct wilc_vif *vif[WILC_NUM_CONCURRENT_IFC];
+       struct list_head vif_list;
+       struct srcu_struct srcu;
+       /*protect vif list queue*/
+       struct mutex vif_mutex;
        u8 open_ifcs;
        /*protect head of transmit queue*/
        struct mutex txq_add_to_head_cs;
@@ -311,7 +309,6 @@ struct wilc {
        uint8_t power_status[DEV_MAX];
        uint8_t keep_awake[DEV_MAX];
        struct mutex cs;
-       int clients_count;
        struct workqueue_struct *hif_workqueue;
 
        struct wilc_cfg cfg;
@@ -321,6 +318,11 @@ struct wilc {
        struct mutex deinit_lock;
        u8 sta_ch;
        u8 op_ch;
+       struct sysfs_attr_group attr_sysfs;
+       struct ieee80211_channel channels[ARRAY_SIZE(wilc_2ghz_channels)];
+       struct ieee80211_rate bitrates[ARRAY_SIZE(wilc_bitrates)];
+       struct ieee80211_supported_band band;
+       u32 cipher_suites[ARRAY_SIZE(wilc_cipher_suites)];
 };
 
 struct wilc_wfi_mon_priv {
@@ -331,8 +333,6 @@ void wilc_frmw_to_host(struct wilc_vif *vif, u8 *buff, u32 size,
                       u32 pkt_offset, u8 status);
 void wilc_mac_indicate(struct wilc *wilc);
 void wilc_netdev_cleanup(struct wilc *wilc);
-int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type,
-                    const struct wilc_hif_func *ops);
 void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size);
 void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode);
 
index 2d6e261..0ec1ee2 100644 (file)
@@ -11,6 +11,7 @@
 #include "wilc_wfi_netdevice.h"
 #include "wilc_wlan_cfg.h"
 #include "wilc_netdev.h"
+#include "wilc_wfi_cfgoperations.h"
 
 #define WAKUP_TRAILS_TIMEOUT           (10000)
 
@@ -51,12 +52,10 @@ static void wilc_wlan_txq_remove(struct wilc *wilc, u8 q_num,
 }
 
 static struct txq_entry_t *
-wilc_wlan_txq_remove_from_head(struct net_device *dev, u8 q_num)
+wilc_wlan_txq_remove_from_head(struct wilc *wilc, u8 q_num)
 {
        struct txq_entry_t *tqe = NULL;
        unsigned long flags;
-       struct wilc_vif *vif = netdev_priv(dev);
-       struct wilc *wilc = vif->wilc;
 
        spin_lock_irqsave(&wilc->txq_spinlock, flags);
 
@@ -272,26 +271,24 @@ static void wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev)
 static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header)
 {
        u8 *bssid, *bssid1;
-       int i = 0;
        struct net_device *mon_netdev = NULL;
+       struct wilc_vif *vif;
 
        bssid = mac_header + 10;
        bssid1 = mac_header + 4;
-       for (i = 0; i < wilc->vif_num; i++) {
-               if (wilc->vif[i]->iftype == WILC_STATION_MODE)
-                       if (ether_addr_equal_unaligned(bssid,
-                                                      wilc->vif[i]->bssid))
-                               return wilc->vif[i]->ndev;
-               if (wilc->vif[i]->iftype == WILC_AP_MODE)
-                       if (ether_addr_equal_unaligned(bssid1,
-                                                      wilc->vif[i]->bssid))
-                               return wilc->vif[i]->ndev;
-               if (wilc->vif[i]->iftype == WILC_MONITOR_MODE)
-                       mon_netdev = wilc->vif[i]->ndev;
+       list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
+               if (vif->iftype == WILC_STATION_MODE)
+                       if (ether_addr_equal_unaligned(bssid, vif->bssid))
+                               return vif->ndev;
+               if (vif->iftype == WILC_AP_MODE)
+                       if (ether_addr_equal_unaligned(bssid1, vif->bssid))
+                               return vif->ndev;
+               if (vif->iftype == WILC_MONITOR_MODE)
+                       mon_netdev = vif->ndev;
        }
 
        if (!mon_netdev)
-               PRINT_WRN(wilc->vif[0]->ndev, GENERIC_DBG, "Invalid handle\n");
+               pr_warn("%s Invalid handle\n", __func__);
        return mon_netdev;
 }
 
@@ -330,6 +327,7 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer,
        tqe->priv = NULL;
        tqe->q_num = AC_VO_Q;
        tqe->ack_idx = NOT_TCP_ACK;
+       tqe->vif = vif;
 
        PRINT_INFO(vif->ndev, TX_DBG,
                   "Adding the config packet at the Queue tail\n");
@@ -521,6 +519,7 @@ int txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
        tqe->buffer_size = buffer_size;
        tqe->tx_complete_func = tx_complete_fn;
        tqe->priv = priv;
+       tqe->vif = vif;
 
        q_num = ac_classify(wilc, tqe);
        if (ac_change(wilc, &q_num)) {
@@ -586,6 +585,7 @@ int txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
        tqe->priv = priv;
        tqe->q_num = AC_BE_Q;
        tqe->ack_idx = NOT_TCP_ACK;
+       tqe->vif = vif;
 
        PRINT_INFO(vif->ndev, TX_DBG, "Adding Mgmt packet to Queue tail\n");
        wilc_wlan_txq_add_to_tail(dev, AC_VO_Q, tqe);
@@ -626,31 +626,23 @@ static struct txq_entry_t *txq_get_next(struct wilc *wilc,
 
 static void rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe)
 {
-       struct wilc_vif *vif = wilc->vif[0];
-
        if (wilc->quit)
                return;
 
        mutex_lock(&wilc->rxq_cs);
        list_add_tail(&rqe->list, &wilc->rxq_head.list);
-       PRINT_INFO(vif->ndev, RX_DBG, "Added to RX queue\n");
        mutex_unlock(&wilc->rxq_cs);
 }
 
 static struct rxq_entry_t *rxq_remove(struct wilc *wilc)
 {
-       struct wilc_vif *vif = wilc->vif[0];
        struct rxq_entry_t *rqe = NULL;
 
-       PRINT_INFO(vif->ndev, RX_DBG, "Getting rxQ element\n");
-
        mutex_lock(&wilc->rxq_cs);
        if (!list_empty(&wilc->rxq_head.list)) {
                rqe = list_first_entry(&wilc->rxq_head.list, struct rxq_entry_t,
                                       list);
                list_del(&rqe->list);
-       } else {
-               PRINT_INFO(vif->ndev, RX_DBG, "Nothing to get from Q\n");
        }
        mutex_unlock(&wilc->rxq_cs);
        return rqe;
@@ -762,7 +754,7 @@ void chip_allow_sleep(struct wilc *wilc, int source)
 void chip_wakeup_wilc1000(struct wilc *wilc, int source)
 {
        u32 ret = 0;
-       u32 reg = 0, clk_status_val = 0, trials = 0;
+       u32 clk_status_val = 0, trials = 0;
        u32 wakeup_reg, wakeup_bit;
        u32 clk_status_reg, clk_status_bit;
        u32 to_host_from_fw_reg, to_host_from_fw_bit;
@@ -790,28 +782,18 @@ void chip_wakeup_wilc1000(struct wilc *wilc, int source)
                to_host_from_fw_bit = BIT(0);
        }
 
-       ret = hif_func->hif_read_reg(wilc, from_host_to_fw_reg, &reg);
+
+       /*USE bit 0 to indicate host wakeup*/
+       ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg,
+                                     from_host_to_fw_bit);
        if (!ret)
                goto _fail_;
 
-       if (!(reg & from_host_to_fw_bit)) {
-               /*USE bit 0 to indicate host wakeup*/
-               ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg,
-                                             reg | from_host_to_fw_bit);
-               if (!ret)
-                       goto _fail_;
-       }
-
-       ret = hif_func->hif_read_reg(wilc, wakeup_reg, &reg);
+       /* Set bit 1 */
+       ret = hif_func->hif_write_reg(wilc, wakeup_reg,
+                                     wakeup_bit);
        if (!ret)
                goto _fail_;
-       /* Set bit 1 */
-       if (!(reg & wakeup_bit)) {
-               ret = hif_func->hif_write_reg(wilc, wakeup_reg,
-                                             reg | wakeup_bit);
-               if (!ret)
-                       goto _fail_;
-       }
 
        do {
                ret = hif_func->hif_read_reg(wilc, clk_status_reg,
@@ -941,7 +923,7 @@ void host_sleep_notify(struct wilc *wilc, int source)
 }
 
 static u8 ac_fw_count[NQUEUES] = {0, 0, 0, 0};
-int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
+int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
 {
        int i, entries = 0;
        u8 k, ac;
@@ -961,9 +943,9 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
        int timeout;
        u32 vmm_table[WILC_VMM_TBL_SIZE];
        u8 ac_pkt_num_to_chip[NQUEUES] = {0, 0, 0, 0};
-       struct wilc_vif *vif = netdev_priv(dev);
-       struct wilc *wilc = vif->wilc;
+       struct wilc_vif *vif;
        const struct wilc_hif_func *func;
+       int srcu_idx;
 
        txb = wilc->tx_buffer;
        if (!wilc->txq_entries) {
@@ -977,11 +959,15 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
                return -1;
 
        mutex_lock(&wilc->txq_add_to_head_cs);
-       wilc_wlan_txq_filter_dup_tcp_ack(dev);
 
-       PRINT_INFO(vif->ndev, TX_DBG, "Getting the head of the TxQ\n");
+       srcu_idx = srcu_read_lock(&wilc->srcu);
+       list_for_each_entry_rcu(vif, &wilc->vif_list, list)
+               wilc_wlan_txq_filter_dup_tcp_ack(vif->ndev);
+       srcu_read_unlock(&wilc->srcu, srcu_idx);
+
        for (ac = 0; ac < NQUEUES; ac++)
                tqe_q[ac] = txq_get_first(wilc, ac);
+
        i = 0;
        sum = 0;
        max_size_over = 0;
@@ -991,7 +977,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
                for (ac = 0; (ac < NQUEUES) && (!max_size_over); ac++) {
                        if (!tqe_q[ac])
                                continue;
-
+                       vif = tqe_q[ac]->vif;
                        ac_exist = 1;
                        for (k = 0; (k < num_pkts_to_add[ac]) &&
                                    (!max_size_over) && tqe_q[ac]; k++) {
@@ -1044,10 +1030,8 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
                num_pkts_to_add = ac_preserve_ratio;
        } while (!max_size_over && ac_exist);
 
-       if (i == 0) {
-               PRINT_INFO(vif->ndev, TX_DBG, "Nothing in TX-Q\n");
+       if (i == 0)
                goto out;
-       }
        vmm_table[i] = 0x0;
 
        acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP, DEV_WIFI);
@@ -1056,7 +1040,8 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
        do {
                ret = func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, &reg);
                if (!ret) {
-                       PRINT_ER(vif->ndev, "fail read reg vmm_tbl_entry..\n");
+                       PRINT_ER(vif->ndev,
+                                "fail read reg vmm_tbl_entry..\n");
                        break;
                }
                if ((reg & 0x1) == 0) {
@@ -1069,7 +1054,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
                if (counter > 200) {
                        counter = 0;
                        PRINT_INFO(vif->ndev, TX_DBG,
-                                   "Looping in tx ctrl , force quit\n");
+                                  "Looping in tx ctrl , force quit\n");
                        ret = func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, 0);
                        break;
                }
@@ -1085,7 +1070,8 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
                                         (u8 *)vmm_table,
                                         ((i + 1) * 4));
                if (!ret) {
-                       PRINT_ER(vif->ndev, "ERR block TX of VMM table.\n");
+                       PRINT_ER(vif->ndev,
+                                "ERR block TX of VMM table.\n");
                        break;
                }
 
@@ -1200,7 +1186,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
                struct txq_entry_t *tqe;
                u32 header, buffer_offset;
 
-               tqe = wilc_wlan_txq_remove_from_head(dev, vmm_entries_ac[i]);
+               tqe = wilc_wlan_txq_remove_from_head(wilc, vmm_entries_ac[i]);
                ac_pkt_num_to_chip[vmm_entries_ac[i]]++;
                if (!tqe)
                        break;
@@ -1208,6 +1194,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
                if (vmm_table[i] == 0)
                        break;
 
+               vif = tqe->vif;
                le32_to_cpus(&vmm_table[i]);
                vmm_sz = (vmm_table[i] & 0x3ff);
                vmm_sz *= 4;
@@ -1224,8 +1211,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
                if (tqe->type == WILC_CFG_PKT) {
                        buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET;
                } else if (tqe->type == WILC_NET_PKT) {
-                       char *bssid = ((struct tx_complete_data *)
-                                      (tqe->priv))->bssid;
+                       char *bssid = tqe->vif->bssid;
                        int prio = tqe->q_num;
 
                        buffer_offset = ETH_ETHERNET_HDR_OFFSET;
@@ -1270,7 +1256,6 @@ out_release_bus:
 out:
        mutex_unlock(&wilc->txq_add_to_head_cs);
 
-       PRINT_INFO(vif->ndev, TX_DBG, "THREAD: Exiting txq\n");
        *txq_count = wilc->txq_entries;
        if (ret == 1)
                cfg_packet_timeout = 0;
@@ -1284,15 +1269,10 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size)
        u32 pkt_len, pkt_offset, tp_len;
        int is_cfg_packet;
        u8 *buff_ptr;
-       struct wilc_vif *vif = wilc->vif[0];
 
        do {
-               PRINT_INFO(vif->ndev, RX_DBG, "Handling rx buffer\n");
                buff_ptr = buffer + offset;
-               memcpy(&header, buff_ptr, 4);
-               le32_to_cpus(&header);
-               PRINT_INFO(vif->ndev, RX_DBG,
-                          "Header = %04x - Offset = %d\n", header, offset);
+               header = get_unaligned_le32(buff_ptr);
 
                is_cfg_packet = (header >> 31) & 0x1;
                pkt_offset = (header >> 22) & 0x1ff;
@@ -1300,8 +1280,7 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size)
                pkt_len = header & 0x7ff;
 
                if (pkt_len == 0 || tp_len == 0) {
-                       PRINT_INFO(vif->ndev, RX_DBG,
-                                  "Data corrupted %d, %d\n",
+                       pr_err("%s: Data corrupted %d, %d\n", __func__,
                                   pkt_len, tp_len);
                        break;
                }
@@ -1314,10 +1293,6 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size)
                        cfg_indicate_rx(wilc, buff_ptr, pkt_len,
                                        &rsp);
                        if (rsp.type == WILC_CFG_RSP) {
-                               PRINT_INFO(vif->ndev, RX_DBG,
-                                       "cfg_seq %d rsp.seq %d\n",
-                                       wilc->cfg_seq_no, rsp.seq_no);
-
                                if (wilc->cfg_seq_no == rsp.seq_no)
                                        complete(&wilc->cfg_event);
                        } else if (rsp.type == WILC_CFG_RSP_STATUS) {
@@ -1332,16 +1307,21 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size)
                        wilc_wfi_handle_monitor_rx(wilc, buff_ptr, pkt_len);
                } else if (pkt_len > 0) {
                        struct net_device *wilc_netdev;
+                       struct wilc_vif *vif;
+                       int srcu_idx;
 
+                       srcu_idx = srcu_read_lock(&wilc->srcu);
                        wilc_netdev = get_if_handler(wilc, buff_ptr);
                        if (!wilc_netdev) {
-                               PRINT_ER(vif->ndev,
-                                        "wilc_netdev in wilc is NULL");
+                               pr_err("%s: wilc_netdev in wilc is NULL\n",
+                                      __func__);
+                               srcu_read_unlock(&wilc->srcu, srcu_idx);
                                return;
                        }
                        vif = netdev_priv(wilc_netdev);
                        wilc_frmw_to_host(vif, buff_ptr, pkt_len,
                                          pkt_offset, PKT_STATUS_NEW);
+                       srcu_read_unlock(&wilc->srcu, srcu_idx);
                }
 
                offset += tp_len;
@@ -1355,34 +1335,25 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc)
        int size;
        u8 *buffer;
        struct rxq_entry_t *rqe;
-       struct wilc_vif *vif = wilc->vif[0];
 
        do {
                if (wilc->quit) {
-                       PRINT_INFO(vif->ndev, RX_DBG,
-                                  "Quitting. Exit handle RX queue\n");
+                       pr_info("%s Quitting. Exit handle RX queue\n",
+                               __func__);
                        complete(&wilc->cfg_event);
                        break;
                }
                rqe = rxq_remove(wilc);
-               if (!rqe) {
-                       PRINT_INFO(vif->ndev, RX_DBG,
-                                  "nothing in RX queue\n");
+               if (!rqe)
                        break;
-               }
 
                buffer = rqe->buffer;
                size = rqe->buffer_size;
-               PRINT_INFO(vif->ndev, RX_DBG,
-                          "rxQ entery Size = %d - Address = %p\n",
-                          size, buffer);
 
                wilc_wlan_handle_rx_buff(wilc, buffer, size);
 
                kfree(rqe);
        } while (1);
-
-       PRINT_INFO(vif->ndev, RX_DBG, "THREAD: Exiting RX thread\n");
 }
 
 static void wilc_unknown_isr_ext(struct wilc *wilc)
@@ -1398,13 +1369,12 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
        u32 retries = 0;
        int ret = 0;
        struct rxq_entry_t *rqe;
-       struct wilc_vif *vif = wilc->vif[0];
 
        size = (int_status & 0x7fff) << 2;
 
        while (!size && retries < 10) {
-               PRINT_ER(vif->ndev,
-                        "RX Size equal zero Trying to read it again\n");
+               pr_err("%s: RX Size equal zero Trying to read it again\n",
+                      __func__);
                wilc->hif_func->hif_read_size(wilc, &size);
                size = (size & 0x7fff) << 2;
                retries++;
@@ -1422,7 +1392,7 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
 
        ret = wilc->hif_func->hif_block_rx_ext(wilc, 0, buffer, size);
        if (!ret) {
-               PRINT_ER(vif->ndev, "fail block rx\n");
+               pr_err("%s: fail block rx\n", __func__);
                return;
        }
 
@@ -1434,9 +1404,6 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
 
        rqe->buffer = buffer;
        rqe->buffer_size = size;
-       PRINT_INFO(vif->ndev, RX_DBG,
-                  "rxq entery Size= %d Address= %p\n",
-                  rqe->buffer_size, rqe->buffer);
        rxq_add(wilc, rqe);
        wilc_wlan_handle_rxq(wilc);
 }
@@ -1444,7 +1411,6 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
 void wilc_handle_isr(struct wilc *wilc)
 {
        u32 int_status;
-       struct wilc_vif *vif = wilc->vif[0];
 
        acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP, DEV_WIFI);
        wilc->hif_func->hif_read_int(wilc, &int_status);
@@ -1453,7 +1419,7 @@ void wilc_handle_isr(struct wilc *wilc)
                wilc_wlan_handle_isr_ext(wilc, int_status);
 
        if (!(int_status & (ALL_INT_EXT))) {
-               PRINT_WRN(vif->ndev, TX_DBG, ">> UNKNOWN_INTERRUPT - 0x%08x\n",
+               pr_warn("%s,>> UNKNOWN_INTERRUPT - 0x%08x\n", __func__,
                          int_status);
                wilc_unknown_isr_ext(wilc);
        }
@@ -1469,20 +1435,15 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
        u8 *dma_buffer;
        int ret = 0;
        u32 reg = 0;
-       struct wilc_vif *vif = wilc->vif[0];
 
        blksz = BIT(12);
 
        dma_buffer = kmalloc(blksz, GFP_KERNEL);
-       if (!dma_buffer) {
-               PRINT_ER(vif->ndev,
-                        "Can't allocate buffer for fw download IO error\n");
+       if (!dma_buffer)
                return -EIO;
-       }
 
        offset = 0;
-       PRINT_INFO(vif->ndev, INIT_DBG, "Downloading firmware size = %d\n",
-                  buffer_size);
+       pr_info("%sDownloading firmware size = %d\n", __func__, buffer_size);
 
        acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP, DEV_WIFI);
 
@@ -1491,14 +1452,12 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
        ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
        wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
        if ((reg & (1ul << 10)) != 0)
-               PRINT_ER(vif->ndev, "Failed to reset Wifi CPU\n");
+               pr_err("%s: Failed to reset Wifi CPU\n", __func__);
 
        release_bus(wilc, WILC_BUS_RELEASE_ONLY, DEV_WIFI);
        do {
-               memcpy(&addr, &buffer[offset], 4);
-               memcpy(&size, &buffer[offset + 4], 4);
-               le32_to_cpus(&addr);
-               le32_to_cpus(&size);
+               addr = get_unaligned_le32(&buffer[offset]);
+               size = get_unaligned_le32(&buffer[offset + 4]);
                acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP, DEV_WIFI);
                offset += 8;
                while (((int)size) && (offset < buffer_size)) {
@@ -1521,10 +1480,10 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
 
                if (!ret) {
                        ret = -EIO;
-                       PRINT_ER(vif->ndev, "Bus error\n");
+                       pr_err("%s Bus error\n", __func__);
                        goto fail;
                }
-               PRINT_INFO(vif->ndev, INIT_DBG, "Offset = %d\n", offset);
+               pr_info("%s Offset = %d\n", __func__, offset);
        } while (offset < buffer_size);
 
 fail:
@@ -1538,7 +1497,6 @@ int wilc_wlan_start(struct wilc *wilc)
 {
        u32 reg = 0;
        int ret;
-       struct wilc_vif *vif = wilc->vif[0];
 
        if (wilc->io_type == WILC_HIF_SDIO ||
            wilc->io_type == WILC_HIF_SDIO_GPIO_IRQ)
@@ -1549,8 +1507,7 @@ int wilc_wlan_start(struct wilc *wilc)
        acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP, DEV_WIFI);
        ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg);
        if (!ret) {
-               PRINT_ER(vif->ndev,
-                        "[wilc start]: fail write reg vmm_core_cfg...\n");
+               pr_err("[wilc start]: fail write reg vmm_core_cfg...\n");
                release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI);
                return -EIO;
        }
@@ -1563,8 +1520,7 @@ int wilc_wlan_start(struct wilc *wilc)
 
        ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg);
        if (!ret) {
-               PRINT_ER(vif->ndev,
-                        "[wilc start]: fail write WILC_GP_REG_1...\n");
+               pr_err("[wilc start]: fail write WILC_GP_REG_1...\n");
                release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI);
                return -EIO;
        }
@@ -1596,7 +1552,6 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif)
 {
        u32 reg = 0;
        int ret;
-       u8 timeout = 10;
 
        acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP, DEV_WIFI);
 
@@ -1605,7 +1560,7 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif)
        if (!ret) {
                PRINT_ER(vif->ndev, "Error while reading reg\n");
                release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI);
-               return ret;
+               return -EIO;
        }
 
        reg &= ~BIT(0);
@@ -1613,7 +1568,7 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif)
        if (!ret) {
                PRINT_ER(vif->ndev, "Error while writing reg\n");
                release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI);
-               return ret;
+               return -EIO;
        }
 
        /* Configure the power sequencer to ignore WIFI sleep signal on making
@@ -1623,7 +1578,7 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif)
        if (!ret) {
                PRINT_ER(vif->ndev, "Error while reading reg\n");
                release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI);
-               return ret;
+               return -EIO;
        }
 
        reg &= ~BIT(28);
@@ -1631,79 +1586,42 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif)
        if (!ret) {
                PRINT_ER(vif->ndev, "Error while writing reg\n");
                release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI);
-               return ret;
+               return -EIO;
        }
 
-       ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
+       ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, &reg);
        if (!ret) {
                PRINT_ER(vif->ndev, "Error while reading reg\n");
                release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI);
-               return ret;
+               return -EIO;
        }
 
-       reg &= ~BIT(10);
-       ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
+       ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0,
+                                       (reg | WILC_ABORT_REQ_BIT));
        if (!ret) {
                PRINT_ER(vif->ndev, "Error while writing reg\n");
                release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI);
-               return ret;
+               return -EIO;
        }
 
-       do {
-               ret = wilc->hif_func->hif_read_reg(wilc,
-                                                  WILC_GLB_RESET_0, &reg);
-               if (!ret) {
-                       PRINT_ER(vif->ndev, "Error while reading reg\n");
-                       release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP,
-                                   DEV_WIFI);
-                       return ret;
-               }
-               PRINT_INFO(vif->ndev, GENERIC_DBG,
-                          "Read RESET Reg %x : Retry%d\n", reg, timeout);
-               if ((reg & BIT(10))) {
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "Bit 10 not reset : Retry %d\n", timeout);
-                       reg &= ~BIT(10);
-                       ret = wilc->hif_func->hif_write_reg(wilc,
-                                                           WILC_GLB_RESET_0,
-                                                           reg);
-                       timeout--;
-               } else {
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "Bit 10 reset after : Retry %d\n", timeout);
-                       ret = wilc->hif_func->hif_read_reg(wilc,
-                                                          WILC_GLB_RESET_0,
-                                                          &reg);
-                       if (!ret) {
-                               PRINT_ER(vif->ndev, "Error reading reg\n");
-                               release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP,
-                                           DEV_WIFI);
-                               return ret;
-                       }
-                       PRINT_INFO(vif->ndev, GENERIC_DBG,
-                                  "Read RESET Reg %x : Retry%d\n", reg,
-                                  timeout);
-                       break;
-               }
-
-       } while (timeout);
-
-       if (wilc->chip == WILC_1000) {
-               reg = (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(8) | BIT(9) |
-                      BIT(26) | BIT(29) | BIT(30) | BIT(31));
-       } else {
-               reg = (BIT(0) | BIT(2) | BIT(3) | BIT(8) | BIT(9) |
-                      BIT(20) | BIT(26) | BIT(29) | BIT(30) | BIT(31));
+       ret = wilc->hif_func->hif_read_reg(wilc, WILC_FW_HOST_COMM, &reg);
+       if (!ret) {
+               PRINT_ER(vif->ndev, "Error while reading reg\n");
+               release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI);
+               return -EIO;
        }
-
-       wilc->hif_func->hif_read_reg(wilc, WILC_FW_HOST_COMM, &reg);
        reg = BIT(0);
 
        ret = wilc->hif_func->hif_write_reg(wilc, WILC_FW_HOST_COMM, reg);
+       if (!ret) {
+               PRINT_ER(vif->ndev, "Error while writing reg\n");
+               release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI);
+               return -EIO;
+       }
 
        release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI);
 
-       return ret;
+       return 0;
 }
 
 void wilc_wlan_cleanup(struct net_device *dev)
@@ -1717,7 +1635,7 @@ void wilc_wlan_cleanup(struct net_device *dev)
        wilc->quit = 1;
        for (ac = 0; ac < NQUEUES; ac++) {
                do {
-                       tqe = wilc_wlan_txq_remove_from_head(dev, ac);
+                       tqe = wilc_wlan_txq_remove_from_head(wilc, ac);
                        if (!tqe)
                                break;
                        if (tqe->tx_complete_func)
@@ -1794,7 +1712,7 @@ int cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer,
 
        if (!wait_for_completion_timeout(&wilc->cfg_event,
                                         WILC_CFG_PKTS_TIMEOUT)) {
-               PRINT_ER(vif->ndev, "Timed Out\n");
+               pr_err("%s Timed Out\n", __func__);
                ret_size = 0;
        }
 
@@ -1832,10 +1750,10 @@ int cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit,
 
        if (!wait_for_completion_timeout(&wilc->cfg_event,
                                         WILC_CFG_PKTS_TIMEOUT)) {
-               PRINT_INFO(vif->ndev, TX_DBG, "Timed Out\n");
+               pr_err("%s Timed Out\n", __func__);
                ret_size = 0;
        }
-       PRINT_INFO(vif->ndev, TX_DBG, "Get Response received\n");
+
        wilc->cfg_frame_offset = 0;
        wilc->cfg_seq_no += 1;
        mutex_unlock(&wilc->cfg_cmd_lock);
@@ -1843,16 +1761,13 @@ int cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit,
        return ret_size;
 }
 
-int cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size)
-{
-       return cfg_get_wid_value(wl, wid, buffer, buffer_size);
-}
 unsigned int cfg_packet_timeout;
 int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids,
-                        u32 count, u32 drv)
+                        u32 count)
 {
        int i;
        int ret = 0;
+       u32 drv = wilc_get_vif_idx(vif);
 
        if (wait_for_recovery) {
                PRINT_INFO(vif->ndev, CORECONFIG_DBG,
index ad230ce..10d187e 100644 (file)
@@ -142,7 +142,7 @@ static inline bool is_wilc3000(u32 id)
 #define WILC_CFG_RSP           1
 #define WILC_CFG_RSP_STATUS    2
 #define WILC_CFG_RSP_SCAN      3
-#define ABORT_INT              BIT(31)
+#define WILC_ABORT_REQ_BIT             BIT(31)
 
 #define WILC_RX_BUFF_SIZE      (96 * 1024)
 #define WILC_TX_BUFF_SIZE      (64 * 1024)
@@ -246,6 +246,7 @@ struct txq_entry_t {
        int buffer_size;
        void *priv;
        int status;
+       struct wilc_vif *vif;
        void (*tx_complete_func)(void *priv, int status);
 };
 
@@ -296,7 +297,6 @@ struct wilc_hif_func {
 struct tx_complete_data {
        int size;
        void *buff;
-       u8 *bssid;
        struct sk_buff *skb;
        struct wilc_vif *vif;
 };
@@ -328,31 +328,29 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif);
 int txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
                              u32 buffer_size,
                              void (*tx_complete_fn)(void *, int));
-int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count);
+int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count);
 void wilc_handle_isr(struct wilc *wilc);
 void wilc_wlan_cleanup(struct net_device *dev);
 int cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer,
                      u32 buffer_size, int commit, u32 drv_handler);
 int cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit,
                      u32 drv_handler);
-int cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size);
 int txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
                               u32 buffer_size,
                               void (*tx_complete_fn)(void *, int));
 
 void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value);
-int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc);
 netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev);
 
-void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size);
+bool wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size);
 void host_wakeup_notify(struct wilc *wilc, int source);
 void host_sleep_notify(struct wilc *wilc, int source);
 void chip_allow_sleep(struct wilc *wilc, int source);
 void chip_wakeup(struct wilc *wilc, int source);
 int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids,
-                        u32 count, u32 drv);
-void wilc_wlan_power_on_sequence(struct wilc *wilc);
-void wilc_wlan_power_off_sequence(struct wilc *wilc);
+                        u32 count);
+int wilc_wlan_power_on_sequence(struct wilc *wilc);
+int wilc_wlan_power_off_sequence(struct wilc *wilc);
 
 void wilc_bt_init(struct wilc *wilc);
 void wilc_bt_deinit(void);
index 2ee45fa..3bea59f 100644 (file)
@@ -8,6 +8,7 @@
 #include "wilc_wlan.h"
 #include "wilc_wlan_cfg.h"
 #include "wilc_wfi_netdevice.h"
+#include "wilc_wfi_cfgoperations.h"
 
 enum cfg_cmd_type {
        CFG_BYTE_CMD    = 0,
@@ -59,105 +60,71 @@ static struct wilc_cfg_bin g_cfg_bin[] = {
 
 static int wilc_wlan_cfg_set_byte(u8 *frame, u32 offset, u16 id, u8 val8)
 {
-       u8 *buf;
 
        if ((offset + 4) >= WILC_MAX_CFG_FRAME_SIZE)
                return 0;
 
-       buf = &frame[offset];
-
-       buf[0] = (u8)id;
-       buf[1] = (u8)(id >> 8);
-       buf[2] = 1;
-       buf[3] = 0;
-       buf[4] = val8;
+       put_unaligned_le16(id, &frame[offset]);
+       put_unaligned_le16(1, &frame[offset + 2]);
+       frame[offset + 4] = val8;
        return 5;
 }
 
 static int wilc_wlan_cfg_set_hword(u8 *frame, u32 offset, u16 id, u16 val16)
 {
-       u8 *buf;
-
        if ((offset + 5) >= WILC_MAX_CFG_FRAME_SIZE)
                return 0;
 
-       buf = &frame[offset];
-
-       buf[0] = (u8)id;
-       buf[1] = (u8)(id >> 8);
-       buf[2] = 2;
-       buf[3] = 0;
-       buf[4] = (u8)val16;
-       buf[5] = (u8)(val16 >> 8);
-
+       put_unaligned_le16(id, &frame[offset]);
+       put_unaligned_le16(2, &frame[offset + 2]);
+       put_unaligned_le16(val16, &frame[offset + 4]);
        return 6;
 }
 
 static int wilc_wlan_cfg_set_word(u8 *frame, u32 offset, u16 id, u32 val32)
 {
-       u8 *buf;
-
        if ((offset + 7) >= WILC_MAX_CFG_FRAME_SIZE)
                return 0;
 
-       buf = &frame[offset];
-
-       buf[0] = (u8)id;
-       buf[1] = (u8)(id >> 8);
-       buf[2] = 4;
-       buf[3] = 0;
-       buf[4] = (u8)val32;
-       buf[5] = (u8)(val32 >> 8);
-       buf[6] = (u8)(val32 >> 16);
-       buf[7] = (u8)(val32 >> 24);
-
+       put_unaligned_le16(id, &frame[offset]);
+       put_unaligned_le16(4, &frame[offset + 2]);
+       put_unaligned_le32(val32, &frame[offset + 4]);
        return 8;
 }
 
 static int wilc_wlan_cfg_set_str(u8 *frame, u32 offset, u16 id, u8 *str,
                                 u32 size)
 {
-       u8 *buf;
-
        if ((offset + size + 4) >= WILC_MAX_CFG_FRAME_SIZE)
                return 0;
 
-       buf = &frame[offset];
-
-       buf[0] = (u8)id;
-       buf[1] = (u8)(id >> 8);
-       buf[2] = (u8)size;
-       buf[3] = (u8)(size >> 8);
+       put_unaligned_le16(id, &frame[offset]);
+       put_unaligned_le16(size, &frame[offset + 2]);
 
        if (str && size != 0)
-               memcpy(&buf[4], str, size);
+               memcpy(&frame[offset + 4], str, size);
 
        return (size + 4);
 }
 
 static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size)
 {
-       u8 *buf;
        u32 i;
        u8 checksum = 0;
 
        if ((offset + size + 5) >= WILC_MAX_CFG_FRAME_SIZE)
                return 0;
 
-       buf = &frame[offset];
-       buf[0] = (u8)id;
-       buf[1] = (u8)(id >> 8);
-       buf[2] = (u8)size;
-       buf[3] = (u8)(size >> 8);
+       put_unaligned_le16(id, &frame[offset]);
+       put_unaligned_le16(size, &frame[offset + 2]);
 
        if ((b) && size != 0) {
-               memcpy(&buf[4], b, size);
+               memcpy(&frame[offset + 4], b, size);
                for (i = 0; i < size; i++)
-                       checksum += buf[i + 4];
+                       checksum += frame[offset + i + 4];
        }
 
-       buf[size + 4] = checksum;
-
+       frame[offset + size + 4] = checksum;
        return (size + 5);
 }
 
@@ -173,14 +140,11 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info,
 {
        u16 wid;
        u32 len = 0, i = 0;
-       struct wilc_vif *vif = wl->vif[0];
 
        while (size > 0) {
                i = 0;
                wid = get_unaligned_le16(info);
 
-               PRINT_D(vif->ndev, GENERIC_DBG, "Processing response for %d\n",
-                       wid);
                switch (GET_WID_TYPE(wid)) {
                case WID_CHAR:
                        do {
@@ -267,7 +231,8 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info,
                                 * DATA
                                 */
                                if (checksum != info[4 + length]) {
-                                       PRINT_ER(vif->ndev, "Checksum Failed");
+                                       pr_err("%s: Checksum Failed\n",
+                                              __func__);
                                        return;
                                }
 
@@ -291,13 +256,11 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info,
 
 static void wilc_wlan_parse_info_frame(struct wilc *wl, u8 *info)
 {
-       struct wilc_vif *vif = wl->vif[0];
        u32 wid, len;
 
        wid = get_unaligned_le16(info);
 
        len = info[2];
-       PRINT_D(vif->ndev, GENERIC_DBG, "Status Len = %d Id= %d\n", len, wid);
 
        if (len == 1 && wid == WID_STATUS) {
                int i = 0;
@@ -361,20 +324,14 @@ int cfg_set_wid(struct wilc_vif *vif, u8 *frame, u32 offset, u16 id, u8 *buf,
 
 int cfg_get_wid(u8 *frame, u32 offset, u16 id)
 {
-       u8 *buf;
-
        if ((offset + 2) >= WILC_MAX_CFG_FRAME_SIZE)
                return 0;
 
-       buf = &frame[offset];
-
-       buf[0] = (u8)id;
-       buf[1] = (u8)(id >> 8);
-
+       put_unaligned_le16(id, &frame[offset]);
        return 2;
 }
 
-int cfg_get_wid_value(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size)
+int cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size)
 {
        u32 type = (wid >> 12) & 0xf;
        int i, ret = 0;
@@ -445,7 +402,7 @@ int cfg_get_wid_value(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size)
                                             (wl->cfg.bin[i].bin[1]<<8);
                                if (buffer_size >= size) {
                                        memcpy(buffer, &wl->cfg.bin[i].bin[2],
-                                               size);
+                                              size);
                                        ret = size;
                                }
                                break;
@@ -453,14 +410,14 @@ int cfg_get_wid_value(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size)
                        i++;
                } while (1);
        } else {
-               PRINT_ER(wl->vif[0]->ndev, "[CFG]: illegal type (%08x)\n", wid);
+               pr_err("[CFG]: illegal type (%08x)\n", wid);
        }
 
        return ret;
 }
 
 void cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size,
-                              struct wilc_cfg_rsp *rsp)
+                    struct wilc_cfg_rsp *rsp)
 {
        u8 msg_type;
        u8 msg_id;
@@ -490,7 +447,7 @@ void cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size,
                rsp->type = WILC_CFG_RSP_STATUS;
                rsp->seq_no = msg_id;
                /*call host interface info parse as well*/
-               PRINT_D(wilc->vif[0]->ndev, RX_DBG, "Info message received\n");
+               pr_info("%s: Info message received\n", __func__);
                wilc_gnrl_async_info_received(wilc, frame - 4, size + 4);
                break;
 
@@ -499,16 +456,14 @@ void cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size,
                break;
 
        case 'S':
-               PRINT_D(wilc->vif[0]->ndev, RX_DBG,
-                       "Scan Notification Received\n");
+               pr_info("%s: Scan Notification Received\n", __func__);
                wilc_scan_complete_received(wilc, frame - 4, size + 4);
                break;
 
        default:
-               PRINT_D(wilc->vif[0]->ndev, RX_DBG,
-                       "Receive unknown message %d-%d-%d-%d-%d-%d-%d-%d\n",
-                        frame[0], frame[1], frame[2], frame[3], frame[4],
-                        frame[5], frame[6], frame[7]);
+               pr_err("%s: Receive unknown message %d-%d-%d-%d-%d-%d-%d-%d\n",
+                      __func__, frame[0], frame[1], frame[2], frame[3],
+                      frame[4], frame[5], frame[6], frame[7]);
                rsp->seq_no = msg_id;
                break;
        }
@@ -540,7 +495,6 @@ int cfg_init(struct wilc *wl)
        if (!str_vals)
                goto out_s;
 
-
        wl->cfg.bin = kmemdup(g_cfg_bin, sizeof(g_cfg_bin), GFP_KERNEL);
        if (!wl->cfg.bin)
                goto out_str_val;
index 3f78a15..d24ab36 100644 (file)
@@ -56,7 +56,7 @@ struct wilc;
 int cfg_set_wid(struct wilc_vif *vif, u8 *frame, u32 offset, u16 id, u8 *buf,
                int size);
 int cfg_get_wid(u8 *frame, u32 offset, u16 id);
-int cfg_get_wid_value(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size);
+int cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size);
 void cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size,
                               struct wilc_cfg_rsp *rsp);
 int cfg_init(struct wilc *wl);
index 2bf853b..6f479ca 100644 (file)
@@ -735,7 +735,6 @@ enum {
        /* NMAC Integer WID list */
        /* Custom Integer WID list */
        WID_GET_INACTIVE_TIME           = 0x2084,
-       WID_SET_OPERATION_MODE          = 0X2086,
        /* EMAC String WID list */
        WID_SSID                        = 0x3000,
        WID_FIRMWARE_VERSION            = 0x3001,
@@ -768,7 +767,7 @@ enum {
        WID_DEVICE_NAME                 = 0x3029, /*Added for CAPI tool */
 
        /* NMAC String WID list */
-       WID_SET_DRV_HANDLER             = 0x3079,
+       WID_SET_OPERATION_MODE          = 0x3079,
        WID_11N_P_ACTION_REQ            = 0x3080,
        WID_HUT_TEST_ID                 = 0x3081,
        WID_PMKID_INFO                  = 0x3082,